codeblog-app 2.2.6 → 2.3.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.
Files changed (69) hide show
  1. package/package.json +8 -71
  2. package/drizzle/0000_init.sql +0 -34
  3. package/drizzle/meta/_journal.json +0 -13
  4. package/drizzle.config.ts +0 -10
  5. package/src/ai/__tests__/chat.test.ts +0 -179
  6. package/src/ai/__tests__/provider.test.ts +0 -198
  7. package/src/ai/__tests__/tools.test.ts +0 -93
  8. package/src/ai/chat.ts +0 -224
  9. package/src/ai/configure.ts +0 -134
  10. package/src/ai/provider.ts +0 -302
  11. package/src/ai/tools.ts +0 -114
  12. package/src/auth/index.ts +0 -47
  13. package/src/auth/oauth.ts +0 -108
  14. package/src/cli/__tests__/commands.test.ts +0 -225
  15. package/src/cli/cmd/agent.ts +0 -97
  16. package/src/cli/cmd/chat.ts +0 -190
  17. package/src/cli/cmd/comment.ts +0 -67
  18. package/src/cli/cmd/config.ts +0 -153
  19. package/src/cli/cmd/feed.ts +0 -53
  20. package/src/cli/cmd/forum.ts +0 -106
  21. package/src/cli/cmd/login.ts +0 -45
  22. package/src/cli/cmd/logout.ts +0 -12
  23. package/src/cli/cmd/me.ts +0 -188
  24. package/src/cli/cmd/post.ts +0 -25
  25. package/src/cli/cmd/publish.ts +0 -64
  26. package/src/cli/cmd/scan.ts +0 -78
  27. package/src/cli/cmd/search.ts +0 -35
  28. package/src/cli/cmd/setup.ts +0 -352
  29. package/src/cli/cmd/tui.ts +0 -20
  30. package/src/cli/cmd/uninstall.ts +0 -281
  31. package/src/cli/cmd/update.ts +0 -123
  32. package/src/cli/cmd/vote.ts +0 -50
  33. package/src/cli/cmd/whoami.ts +0 -18
  34. package/src/cli/mcp-print.ts +0 -6
  35. package/src/cli/ui.ts +0 -250
  36. package/src/config/index.ts +0 -55
  37. package/src/flag/index.ts +0 -23
  38. package/src/global/index.ts +0 -38
  39. package/src/id/index.ts +0 -20
  40. package/src/index.ts +0 -200
  41. package/src/mcp/__tests__/client.test.ts +0 -149
  42. package/src/mcp/__tests__/e2e.ts +0 -327
  43. package/src/mcp/__tests__/integration.ts +0 -148
  44. package/src/mcp/client.ts +0 -148
  45. package/src/server/index.ts +0 -48
  46. package/src/storage/chat.ts +0 -71
  47. package/src/storage/db.ts +0 -85
  48. package/src/storage/schema.sql.ts +0 -39
  49. package/src/storage/schema.ts +0 -1
  50. package/src/tui/app.tsx +0 -184
  51. package/src/tui/commands.ts +0 -186
  52. package/src/tui/context/exit.tsx +0 -15
  53. package/src/tui/context/helper.tsx +0 -25
  54. package/src/tui/context/route.tsx +0 -24
  55. package/src/tui/context/theme.tsx +0 -470
  56. package/src/tui/routes/home.tsx +0 -660
  57. package/src/tui/routes/model.tsx +0 -210
  58. package/src/tui/routes/notifications.tsx +0 -87
  59. package/src/tui/routes/post.tsx +0 -102
  60. package/src/tui/routes/search.tsx +0 -105
  61. package/src/tui/routes/setup.tsx +0 -255
  62. package/src/tui/routes/trending.tsx +0 -107
  63. package/src/util/__tests__/context.test.ts +0 -31
  64. package/src/util/__tests__/lazy.test.ts +0 -37
  65. package/src/util/context.ts +0 -23
  66. package/src/util/error.ts +0 -46
  67. package/src/util/lazy.ts +0 -18
  68. package/src/util/log.ts +0 -142
  69. package/tsconfig.json +0 -11
@@ -1,123 +0,0 @@
1
- import type { CommandModule } from "yargs"
2
- import { UI } from "../ui"
3
-
4
- export const UpdateCommand: CommandModule = {
5
- command: "update",
6
- describe: "Update codeblog CLI to the latest version",
7
- builder: (yargs) =>
8
- yargs.option("force", {
9
- describe: "Force update even if already on latest",
10
- type: "boolean",
11
- default: false,
12
- }),
13
- handler: async (args) => {
14
- const pkg = await import("../../../package.json")
15
- const current = pkg.version
16
-
17
- UI.info(`Current version: v${current}`)
18
- UI.info("Checking for updates...")
19
-
20
- const checkController = new AbortController()
21
- const checkTimeout = setTimeout(() => checkController.abort(), 10_000)
22
- let res: Response
23
- try {
24
- res = await fetch("https://registry.npmjs.org/codeblog-app/latest", { signal: checkController.signal })
25
- } catch (e: any) {
26
- clearTimeout(checkTimeout)
27
- if (e.name === "AbortError") {
28
- UI.error("Version check timed out (10s). Please check your network and try again.")
29
- } else {
30
- UI.error(`Failed to check for updates: ${e.message}`)
31
- }
32
- process.exitCode = 1
33
- return
34
- }
35
- clearTimeout(checkTimeout)
36
- if (!res.ok) {
37
- UI.error("Failed to check for updates")
38
- process.exitCode = 1
39
- return
40
- }
41
-
42
- const data = await res.json() as { version: string }
43
- const latest = data.version
44
-
45
- if (current === latest && !args.force) {
46
- UI.success(`Already on latest version v${current}`)
47
- return
48
- }
49
-
50
- UI.info(`Updating v${current} → v${latest}...`)
51
-
52
- const os = process.platform === "win32" ? "windows" : process.platform === "darwin" ? "darwin" : "linux"
53
- const arch = process.arch === "arm64" ? "arm64" : "x64"
54
- const platform = `${os}-${arch}`
55
- const pkg_name = `codeblog-app-${platform}`
56
- const url = `https://registry.npmjs.org/${pkg_name}/-/${pkg_name}-${latest}.tgz`
57
-
58
- const tmpdir = (await import("os")).tmpdir()
59
- const path = await import("path")
60
- const fs = await import("fs/promises")
61
- const tmp = path.join(tmpdir, `codeblog-update-${Date.now()}`)
62
- await fs.mkdir(tmp, { recursive: true })
63
-
64
- UI.info("Downloading...")
65
- const tgz = path.join(tmp, "pkg.tgz")
66
- const dlController = new AbortController()
67
- const dlTimeout = setTimeout(() => dlController.abort(), 60_000)
68
- let dlRes: Response
69
- try {
70
- dlRes = await fetch(url, { signal: dlController.signal })
71
- } catch (e: any) {
72
- clearTimeout(dlTimeout)
73
- await fs.rm(tmp, { recursive: true, force: true }).catch(() => {})
74
- if (e.name === "AbortError") {
75
- UI.error("Download timed out (60s). Please check your network and try again.")
76
- } else {
77
- UI.error(`Download failed: ${e.message}`)
78
- }
79
- process.exitCode = 1
80
- return
81
- }
82
- clearTimeout(dlTimeout)
83
- if (!dlRes.ok) {
84
- UI.error(`Failed to download update for ${platform} (HTTP ${dlRes.status})`)
85
- await fs.rm(tmp, { recursive: true, force: true }).catch(() => {})
86
- process.exitCode = 1
87
- return
88
- }
89
-
90
- const arrayBuf = await dlRes.arrayBuffer()
91
- await fs.writeFile(tgz, Buffer.from(arrayBuf))
92
-
93
- UI.info("Extracting...")
94
- const proc = Bun.spawn(["tar", "-xzf", tgz, "-C", tmp], { stdout: "ignore", stderr: "ignore" })
95
- await proc.exited
96
-
97
- const bin = process.execPath
98
- const ext = os === "windows" ? ".exe" : ""
99
- const src = path.join(tmp, "package", "bin", `codeblog${ext}`)
100
-
101
- UI.info("Installing...")
102
- // On macOS/Linux, remove the running binary first to avoid ETXTBSY
103
- if (os !== "windows") {
104
- try {
105
- await fs.unlink(bin)
106
- } catch {
107
- // ignore if removal fails
108
- }
109
- }
110
- await fs.copyFile(src, bin)
111
- if (os !== "windows") {
112
- await fs.chmod(bin, 0o755)
113
- }
114
- if (os === "darwin") {
115
- const cs = Bun.spawn(["codesign", "--sign", "-", "--force", bin], { stdout: "ignore", stderr: "ignore" })
116
- await cs.exited
117
- }
118
-
119
- await fs.rm(tmp, { recursive: true, force: true })
120
-
121
- UI.success(`Updated to v${latest}!`)
122
- },
123
- }
@@ -1,50 +0,0 @@
1
- import type { CommandModule } from "yargs"
2
- import { McpBridge } from "../../mcp/client"
3
- import { UI } from "../ui"
4
-
5
- export const VoteCommand: CommandModule = {
6
- command: "vote <post_id>",
7
- describe: "Vote on a post (up/down/remove)",
8
- builder: (yargs) =>
9
- yargs
10
- .positional("post_id", {
11
- describe: "Post ID to vote on",
12
- type: "string",
13
- demandOption: true,
14
- })
15
- .option("up", {
16
- alias: "u",
17
- describe: "Upvote",
18
- type: "boolean",
19
- })
20
- .option("down", {
21
- alias: "d",
22
- describe: "Downvote",
23
- type: "boolean",
24
- })
25
- .option("remove", {
26
- describe: "Remove existing vote",
27
- type: "boolean",
28
- })
29
- .conflicts("up", "down")
30
- .conflicts("up", "remove")
31
- .conflicts("down", "remove"),
32
- handler: async (args) => {
33
- let value = 1 // default upvote
34
- if (args.down) value = -1
35
- if (args.remove) value = 0
36
-
37
- try {
38
- const text = await McpBridge.callTool("vote_on_post", {
39
- post_id: args.post_id,
40
- value,
41
- })
42
- console.log("")
43
- console.log(` ${text}`)
44
- console.log("")
45
- } catch (err) {
46
- UI.error(`Vote failed: ${err instanceof Error ? err.message : String(err)}`)
47
- process.exitCode = 1
48
- }
49
- },
50
- }
@@ -1,18 +0,0 @@
1
- import type { CommandModule } from "yargs"
2
- import { mcpPrint } from "../mcp-print"
3
- import { UI } from "../ui"
4
-
5
- export const WhoamiCommand: CommandModule = {
6
- command: "whoami",
7
- describe: "Show current auth status",
8
- handler: async () => {
9
- try {
10
- console.log("")
11
- await mcpPrint("codeblog_status")
12
- console.log("")
13
- } catch (err) {
14
- UI.error(`Status check failed: ${err instanceof Error ? err.message : String(err)}`)
15
- process.exitCode = 1
16
- }
17
- },
18
- }
@@ -1,6 +0,0 @@
1
- import { McpBridge } from "../mcp/client"
2
-
3
- export async function mcpPrint(tool: string, args: Record<string, unknown> = {}) {
4
- const text = await McpBridge.callTool(tool, args)
5
- for (const line of text.split("\n")) console.log(` ${line}`)
6
- }
package/src/cli/ui.ts DELETED
@@ -1,250 +0,0 @@
1
- import { EOL } from "os"
2
-
3
- export namespace UI {
4
- export const Style = {
5
- TEXT_HIGHLIGHT: "\x1b[96m",
6
- TEXT_HIGHLIGHT_BOLD: "\x1b[96m\x1b[1m",
7
- TEXT_DIM: "\x1b[90m",
8
- TEXT_DIM_BOLD: "\x1b[90m\x1b[1m",
9
- TEXT_NORMAL: "\x1b[0m",
10
- TEXT_NORMAL_BOLD: "\x1b[1m",
11
- TEXT_WARNING: "\x1b[93m",
12
- TEXT_WARNING_BOLD: "\x1b[93m\x1b[1m",
13
- TEXT_DANGER: "\x1b[91m",
14
- TEXT_DANGER_BOLD: "\x1b[91m\x1b[1m",
15
- TEXT_SUCCESS: "\x1b[92m",
16
- TEXT_SUCCESS_BOLD: "\x1b[92m\x1b[1m",
17
- TEXT_INFO: "\x1b[94m",
18
- TEXT_INFO_BOLD: "\x1b[94m\x1b[1m",
19
- }
20
-
21
- export function println(...message: string[]) {
22
- print(...message)
23
- Bun.stderr.write(EOL)
24
- }
25
-
26
- export function print(...message: string[]) {
27
- Bun.stderr.write(message.join(" "))
28
- }
29
-
30
- export function logo() {
31
- const orange = "\x1b[38;5;214m"
32
- const cyan = "\x1b[36m"
33
- const reset = "\x1b[0m"
34
- return [
35
- "",
36
- `${orange} ██████╗ ██████╗ ██████╗ ███████╗${cyan}██████╗ ██╗ ██████╗ ██████╗ ${reset}`,
37
- `${orange} ██╔════╝██╔═══██╗██╔══██╗██╔════╝${cyan}██╔══██╗██║ ██╔═══██╗██╔════╝ ${reset}`,
38
- `${orange} ██║ ██║ ██║██║ ██║█████╗ ${cyan}██████╔╝██║ ██║ ██║██║ ███╗${reset}`,
39
- `${orange} ██║ ██║ ██║██║ ██║██╔══╝ ${cyan}██╔══██╗██║ ██║ ██║██║ ██║${reset}`,
40
- `${orange} ╚██████╗╚██████╔╝██████╔╝███████╗${cyan}██████╔╝███████╗╚██████╔╝╚██████╔╝${reset}`,
41
- `${orange} ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝${cyan}╚═════╝ ╚══════╝ ╚═════╝ ╚═════╝ ${reset}`,
42
- "",
43
- ` ${Style.TEXT_DIM}The AI-powered coding forum in your terminal${Style.TEXT_NORMAL}`,
44
- "",
45
- ].join(EOL)
46
- }
47
-
48
- export function error(message: string) {
49
- println(Style.TEXT_DANGER_BOLD + "Error: " + Style.TEXT_NORMAL + message)
50
- }
51
-
52
- export function success(message: string) {
53
- println(Style.TEXT_SUCCESS_BOLD + "✓ " + Style.TEXT_NORMAL + message)
54
- }
55
-
56
- export function info(message: string) {
57
- println(Style.TEXT_INFO + "ℹ " + Style.TEXT_NORMAL + message)
58
- }
59
-
60
- export function warn(message: string) {
61
- println(Style.TEXT_WARNING + "⚠ " + Style.TEXT_NORMAL + message)
62
- }
63
-
64
- export async function input(prompt: string): Promise<string> {
65
- const readline = require("readline")
66
- const rl = readline.createInterface({ input: process.stdin, output: process.stdout })
67
- return new Promise((resolve) => {
68
- rl.question(prompt, (answer: string) => {
69
- rl.close()
70
- resolve(answer.trim())
71
- })
72
- })
73
- }
74
-
75
- /**
76
- * Input with ESC support. Returns null if user presses Escape, otherwise the input string.
77
- */
78
- export async function inputWithEscape(prompt: string): Promise<string | null> {
79
- const stdin = process.stdin
80
- process.stderr.write(prompt)
81
-
82
- return new Promise((resolve) => {
83
- const wasRaw = stdin.isRaw
84
- if (stdin.isTTY && stdin.setRawMode) stdin.setRawMode(true)
85
-
86
- let buf = ""
87
- const onData = (ch: Buffer) => {
88
- const c = ch.toString("utf8")
89
- if (c === "\u0003") {
90
- // Ctrl+C
91
- if (stdin.isTTY && stdin.setRawMode) stdin.setRawMode(wasRaw ?? false)
92
- stdin.removeListener("data", onData)
93
- process.exit(130)
94
- }
95
- if (c === "\x1b") {
96
- // Escape
97
- if (stdin.isTTY && stdin.setRawMode) stdin.setRawMode(wasRaw ?? false)
98
- stdin.removeListener("data", onData)
99
- process.stderr.write("\n")
100
- resolve(null)
101
- return
102
- }
103
- if (c === "\r" || c === "\n") {
104
- // Enter
105
- if (stdin.isTTY && stdin.setRawMode) stdin.setRawMode(wasRaw ?? false)
106
- stdin.removeListener("data", onData)
107
- process.stderr.write("\n")
108
- resolve(buf)
109
- return
110
- }
111
- if (c === "\u007f" || c === "\b") {
112
- // Backspace
113
- if (buf.length > 0) {
114
- buf = buf.slice(0, -1)
115
- process.stderr.write("\b \b")
116
- }
117
- return
118
- }
119
- // Regular character
120
- const clean = c.replace(/[\x00-\x1f\x7f]/g, "")
121
- if (clean) {
122
- buf += clean
123
- process.stderr.write(clean)
124
- }
125
- }
126
- stdin.on("data", onData)
127
- })
128
- }
129
-
130
- export async function password(prompt: string): Promise<string> {
131
- const readline = require("readline")
132
- const rl = readline.createInterface({ input: process.stdin, output: process.stderr, terminal: true })
133
- return new Promise((resolve) => {
134
- // Disable echoing by writing the prompt manually and muting stdout
135
- process.stderr.write(prompt)
136
- const stdin = process.stdin
137
- const wasRaw = stdin.isRaw
138
- if (stdin.isTTY && stdin.setRawMode) stdin.setRawMode(true)
139
-
140
- let buf = ""
141
- const onData = (ch: Buffer) => {
142
- const c = ch.toString("utf8")
143
- if (c === "\n" || c === "\r" || c === "\u0004") {
144
- if (stdin.isTTY && stdin.setRawMode) stdin.setRawMode(wasRaw ?? false)
145
- stdin.removeListener("data", onData)
146
- process.stderr.write("\n")
147
- rl.close()
148
- resolve(buf.trim())
149
- } else if (c === "\u007f" || c === "\b") {
150
- // backspace
151
- if (buf.length > 0) buf = buf.slice(0, -1)
152
- } else if (c === "\u0003") {
153
- // Ctrl+C
154
- if (stdin.isTTY && stdin.setRawMode) stdin.setRawMode(wasRaw ?? false)
155
- stdin.removeListener("data", onData)
156
- rl.close()
157
- process.exit(130)
158
- } else {
159
- buf += c
160
- process.stderr.write("*")
161
- }
162
- }
163
- stdin.on("data", onData)
164
- })
165
- }
166
-
167
- export async function select(prompt: string, options: string[]): Promise<number> {
168
- console.log(prompt)
169
- for (let i = 0; i < options.length; i++) {
170
- console.log(` ${Style.TEXT_HIGHLIGHT}[${i + 1}]${Style.TEXT_NORMAL} ${options[i]}`)
171
- }
172
- console.log("")
173
- const answer = await input(` Choice [1]: `)
174
- const num = parseInt(answer, 10)
175
- if (!answer) return 0
176
- if (isNaN(num) || num < 1 || num > options.length) return 0
177
- return num - 1
178
- }
179
-
180
- export async function waitKey(prompt: string, keys: string[]): Promise<string> {
181
- const stdin = process.stdin
182
- process.stderr.write(` ${Style.TEXT_DIM}${prompt}${Style.TEXT_NORMAL}`)
183
-
184
- return new Promise((resolve) => {
185
- const wasRaw = stdin.isRaw
186
- if (stdin.isTTY && stdin.setRawMode) stdin.setRawMode(true)
187
-
188
- const onData = (ch: Buffer) => {
189
- const c = ch.toString("utf8")
190
- if (c === "\u0003") {
191
- // Ctrl+C
192
- if (stdin.isTTY && stdin.setRawMode) stdin.setRawMode(wasRaw ?? false)
193
- stdin.removeListener("data", onData)
194
- process.exit(130)
195
- }
196
- const key = (c === "\r" || c === "\n") ? "enter" : c === "\x1b" ? "escape" : c.toLowerCase()
197
- if (keys.includes(key)) {
198
- if (stdin.isTTY && stdin.setRawMode) stdin.setRawMode(wasRaw ?? false)
199
- stdin.removeListener("data", onData)
200
- process.stderr.write("\n")
201
- resolve(key)
202
- }
203
- }
204
- stdin.on("data", onData)
205
- })
206
- }
207
-
208
- /**
209
- * Wait for Enter key (or Esc to skip). Returns "enter" or "escape".
210
- */
211
- export async function waitEnter(prompt?: string): Promise<"enter" | "escape"> {
212
- return waitKey(prompt || "Press Enter to continue...", ["enter", "escape"]) as Promise<"enter" | "escape">
213
- }
214
-
215
- /**
216
- * Streaming typewriter effect — prints text character by character to stderr.
217
- */
218
- export async function typeText(text: string, opts?: { charDelay?: number; prefix?: string }) {
219
- const delay = opts?.charDelay ?? 12
220
- const prefix = opts?.prefix ?? " "
221
- Bun.stderr.write(prefix)
222
- for (const ch of text) {
223
- Bun.stderr.write(ch)
224
- if (delay > 0) await Bun.sleep(delay)
225
- }
226
- Bun.stderr.write(EOL)
227
- }
228
-
229
- /**
230
- * Clean markdown formatting from MCP tool output for CLI display.
231
- * Removes **bold**, *italic*, keeps structure readable.
232
- */
233
- export function cleanMarkdown(text: string): string {
234
- return text
235
- .replace(/\*\*(.+?)\*\*/g, "$1") // **bold** → bold
236
- .replace(/\*(.+?)\*/g, "$1") // *italic* → italic
237
- .replace(/`([^`]+)`/g, "$1") // `code` → code
238
- .replace(/^#{1,6}\s+/gm, "") // ### heading → heading
239
- .replace(/^---+$/gm, "──────────────────────────────────") // horizontal rule
240
- }
241
-
242
- /**
243
- * Print a horizontal divider.
244
- */
245
- export function divider() {
246
- println("")
247
- println(` ${Style.TEXT_DIM}──────────────────────────────────${Style.TEXT_NORMAL}`)
248
- println("")
249
- }
250
- }
@@ -1,55 +0,0 @@
1
- import path from "path"
2
- import { Global } from "../global"
3
-
4
- const CONFIG_FILE = path.join(Global.Path.config, "config.json")
5
-
6
- export namespace Config {
7
- export interface ProviderConfig {
8
- api_key: string
9
- base_url?: string
10
- }
11
-
12
- export interface CodeblogConfig {
13
- api_url: string
14
- api_key?: string
15
- token?: string
16
- model?: string
17
- default_language?: string
18
- activeAgent?: string
19
- providers?: Record<string, ProviderConfig>
20
- }
21
-
22
- const defaults: CodeblogConfig = {
23
- api_url: "https://codeblog.ai",
24
- }
25
-
26
- export const filepath = CONFIG_FILE
27
-
28
- export async function load(): Promise<CodeblogConfig> {
29
- const file = Bun.file(CONFIG_FILE)
30
- const data = await file.json().catch(() => ({}))
31
- return { ...defaults, ...data }
32
- }
33
-
34
- export async function save(config: Partial<CodeblogConfig>) {
35
- const current = await load()
36
- const merged = { ...current, ...config }
37
- await Bun.write(Bun.file(CONFIG_FILE, { mode: 0o600 }), JSON.stringify(merged, null, 2))
38
- }
39
-
40
- export async function url() {
41
- return process.env.CODEBLOG_URL || (await load()).api_url || "https://codeblog.ai"
42
- }
43
-
44
- export async function key() {
45
- return process.env.CODEBLOG_API_KEY || (await load()).api_key || ""
46
- }
47
-
48
- export async function token() {
49
- return process.env.CODEBLOG_TOKEN || (await load()).token || ""
50
- }
51
-
52
- export async function language() {
53
- return process.env.CODEBLOG_LANGUAGE || (await load()).default_language
54
- }
55
- }
package/src/flag/index.ts DELETED
@@ -1,23 +0,0 @@
1
- function truthy(key: string) {
2
- const value = process.env[key]?.toLowerCase()
3
- return value === "true" || value === "1"
4
- }
5
-
6
- export namespace Flag {
7
- export const CODEBLOG_URL = process.env["CODEBLOG_URL"]
8
- export const CODEBLOG_API_KEY = process.env["CODEBLOG_API_KEY"]
9
- export const CODEBLOG_TOKEN = process.env["CODEBLOG_TOKEN"]
10
- export const CODEBLOG_DEBUG = truthy("CODEBLOG_DEBUG")
11
- export const CODEBLOG_DISABLE_AUTOUPDATE = truthy("CODEBLOG_DISABLE_AUTOUPDATE")
12
- export const CODEBLOG_DISABLE_SCANNER_CACHE = truthy("CODEBLOG_DISABLE_SCANNER_CACHE")
13
- export const CODEBLOG_TEST_HOME = process.env["CODEBLOG_TEST_HOME"]
14
- export declare const CODEBLOG_CLIENT: string
15
- }
16
-
17
- Object.defineProperty(Flag, "CODEBLOG_CLIENT", {
18
- get() {
19
- return process.env["CODEBLOG_CLIENT"] ?? "cli"
20
- },
21
- enumerable: true,
22
- configurable: false,
23
- })
@@ -1,38 +0,0 @@
1
- import fs from "fs/promises"
2
- import { xdgData, xdgCache, xdgConfig, xdgState } from "xdg-basedir"
3
- import path from "path"
4
- import os from "os"
5
-
6
- const app = "codeblog"
7
-
8
- const home = process.env.CODEBLOG_TEST_HOME || os.homedir()
9
- const win = os.platform() === "win32"
10
- const appdata = process.env.APPDATA || path.join(home, "AppData", "Roaming")
11
- const localappdata = process.env.LOCALAPPDATA || path.join(home, "AppData", "Local")
12
-
13
- const data = win ? path.join(localappdata, app) : path.join(xdgData || path.join(home, ".local", "share"), app)
14
- const cache = win ? path.join(localappdata, app, "cache") : path.join(xdgCache || path.join(home, ".cache"), app)
15
- const config = win ? path.join(appdata, app) : path.join(xdgConfig || path.join(home, ".config"), app)
16
- const state = win ? path.join(localappdata, app, "state") : path.join(xdgState || path.join(home, ".local", "state"), app)
17
-
18
- export namespace Global {
19
- export const Path = {
20
- get home() {
21
- return process.env.CODEBLOG_TEST_HOME || os.homedir()
22
- },
23
- data,
24
- bin: path.join(data, "bin"),
25
- log: path.join(data, "log"),
26
- cache,
27
- config,
28
- state,
29
- }
30
- }
31
-
32
- await Promise.all([
33
- fs.mkdir(Global.Path.data, { recursive: true }),
34
- fs.mkdir(Global.Path.config, { recursive: true }),
35
- fs.mkdir(Global.Path.state, { recursive: true }),
36
- fs.mkdir(Global.Path.log, { recursive: true }),
37
- fs.mkdir(Global.Path.bin, { recursive: true }),
38
- ])
package/src/id/index.ts DELETED
@@ -1,20 +0,0 @@
1
- import { randomBytes } from "crypto"
2
-
3
- export namespace ID {
4
- export function generate(prefix = ""): string {
5
- const bytes = randomBytes(12).toString("hex")
6
- return prefix ? `${prefix}_${bytes}` : bytes
7
- }
8
-
9
- export function short(): string {
10
- return randomBytes(6).toString("hex")
11
- }
12
-
13
- export function uuid(): string {
14
- return crypto.randomUUID()
15
- }
16
-
17
- export function timestamp(): string {
18
- return `${Date.now()}-${randomBytes(4).toString("hex")}`
19
- }
20
- }