@bloxystudios/bloxycode 1.0.2 → 1.0.5
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/bin/bloxycode +11 -8
- package/package.json +16 -143
- package/postinstall.mjs +129 -0
- package/LICENSE +0 -21
- package/README.md +0 -286
- package/src/acp/README.md +0 -164
- package/src/acp/agent.ts +0 -1437
- package/src/acp/session.ts +0 -105
- package/src/acp/types.ts +0 -22
- package/src/agent/agent.ts +0 -356
- package/src/agent/generate.txt +0 -75
- package/src/agent/prompt/bloxy.txt +0 -46
- package/src/agent/prompt/compaction.txt +0 -12
- package/src/agent/prompt/explore.txt +0 -18
- package/src/agent/prompt/summary.txt +0 -11
- package/src/agent/prompt/title.txt +0 -44
- package/src/auth/index.ts +0 -73
- package/src/bloxy/event.ts +0 -41
- package/src/bloxy/index.ts +0 -5
- package/src/bloxy/parser.ts +0 -263
- package/src/bloxy/prompt.ts +0 -121
- package/src/bloxy/runner.ts +0 -193
- package/src/bloxy/state.ts +0 -246
- package/src/bun/index.ts +0 -134
- package/src/bus/bus-event.ts +0 -43
- package/src/bus/global.ts +0 -10
- package/src/bus/index.ts +0 -105
- package/src/cli/bootstrap.ts +0 -17
- package/src/cli/cmd/acp.ts +0 -69
- package/src/cli/cmd/agent.ts +0 -257
- package/src/cli/cmd/auth.ts +0 -400
- package/src/cli/cmd/cmd.ts +0 -7
- package/src/cli/cmd/debug/agent.ts +0 -167
- package/src/cli/cmd/debug/config.ts +0 -16
- package/src/cli/cmd/debug/file.ts +0 -97
- package/src/cli/cmd/debug/index.ts +0 -48
- package/src/cli/cmd/debug/lsp.ts +0 -52
- package/src/cli/cmd/debug/ripgrep.ts +0 -87
- package/src/cli/cmd/debug/scrap.ts +0 -16
- package/src/cli/cmd/debug/skill.ts +0 -16
- package/src/cli/cmd/debug/snapshot.ts +0 -52
- package/src/cli/cmd/export.ts +0 -88
- package/src/cli/cmd/generate.ts +0 -38
- package/src/cli/cmd/github.ts +0 -1548
- package/src/cli/cmd/import.ts +0 -98
- package/src/cli/cmd/mcp.ts +0 -755
- package/src/cli/cmd/models.ts +0 -77
- package/src/cli/cmd/pr.ts +0 -112
- package/src/cli/cmd/run.ts +0 -395
- package/src/cli/cmd/serve.ts +0 -20
- package/src/cli/cmd/session.ts +0 -135
- package/src/cli/cmd/stats.ts +0 -402
- package/src/cli/cmd/tui/app.tsx +0 -771
- package/src/cli/cmd/tui/attach.ts +0 -39
- package/src/cli/cmd/tui/component/border.tsx +0 -21
- package/src/cli/cmd/tui/component/dialog-agent.tsx +0 -31
- package/src/cli/cmd/tui/component/dialog-command.tsx +0 -148
- package/src/cli/cmd/tui/component/dialog-mcp.tsx +0 -86
- package/src/cli/cmd/tui/component/dialog-model.tsx +0 -234
- package/src/cli/cmd/tui/component/dialog-provider.tsx +0 -256
- package/src/cli/cmd/tui/component/dialog-session-list.tsx +0 -114
- package/src/cli/cmd/tui/component/dialog-session-rename.tsx +0 -31
- package/src/cli/cmd/tui/component/dialog-stash.tsx +0 -87
- package/src/cli/cmd/tui/component/dialog-status.tsx +0 -164
- package/src/cli/cmd/tui/component/dialog-tag.tsx +0 -44
- package/src/cli/cmd/tui/component/dialog-theme-list.tsx +0 -50
- package/src/cli/cmd/tui/component/logo.tsx +0 -102
- package/src/cli/cmd/tui/component/prompt/autocomplete.tsx +0 -653
- package/src/cli/cmd/tui/component/prompt/frecency.tsx +0 -89
- package/src/cli/cmd/tui/component/prompt/history.tsx +0 -108
- package/src/cli/cmd/tui/component/prompt/index.tsx +0 -1138
- package/src/cli/cmd/tui/component/prompt/stash.tsx +0 -101
- package/src/cli/cmd/tui/component/textarea-keybindings.ts +0 -73
- package/src/cli/cmd/tui/component/tips.tsx +0 -153
- package/src/cli/cmd/tui/component/todo-item.tsx +0 -32
- package/src/cli/cmd/tui/context/args.tsx +0 -14
- package/src/cli/cmd/tui/context/directory.ts +0 -13
- package/src/cli/cmd/tui/context/exit.tsx +0 -23
- package/src/cli/cmd/tui/context/helper.tsx +0 -25
- package/src/cli/cmd/tui/context/keybind.tsx +0 -101
- package/src/cli/cmd/tui/context/kv.tsx +0 -52
- package/src/cli/cmd/tui/context/local.tsx +0 -402
- package/src/cli/cmd/tui/context/prompt.tsx +0 -18
- package/src/cli/cmd/tui/context/route.tsx +0 -46
- package/src/cli/cmd/tui/context/sdk.tsx +0 -94
- package/src/cli/cmd/tui/context/sync.tsx +0 -470
- package/src/cli/cmd/tui/context/theme/aura.json +0 -69
- package/src/cli/cmd/tui/context/theme/ayu.json +0 -80
- package/src/cli/cmd/tui/context/theme/bloxycode.json +0 -245
- package/src/cli/cmd/tui/context/theme/carbonfox.json +0 -248
- package/src/cli/cmd/tui/context/theme/catppuccin-frappe.json +0 -233
- package/src/cli/cmd/tui/context/theme/catppuccin-macchiato.json +0 -233
- package/src/cli/cmd/tui/context/theme/catppuccin.json +0 -112
- package/src/cli/cmd/tui/context/theme/cobalt2.json +0 -228
- package/src/cli/cmd/tui/context/theme/cursor.json +0 -249
- package/src/cli/cmd/tui/context/theme/dracula.json +0 -219
- package/src/cli/cmd/tui/context/theme/everforest.json +0 -241
- package/src/cli/cmd/tui/context/theme/flexoki.json +0 -237
- package/src/cli/cmd/tui/context/theme/github.json +0 -233
- package/src/cli/cmd/tui/context/theme/gruvbox.json +0 -242
- package/src/cli/cmd/tui/context/theme/kanagawa.json +0 -77
- package/src/cli/cmd/tui/context/theme/lucent-orng.json +0 -237
- package/src/cli/cmd/tui/context/theme/material.json +0 -235
- package/src/cli/cmd/tui/context/theme/matrix.json +0 -77
- package/src/cli/cmd/tui/context/theme/mercury.json +0 -252
- package/src/cli/cmd/tui/context/theme/monokai.json +0 -221
- package/src/cli/cmd/tui/context/theme/nightowl.json +0 -221
- package/src/cli/cmd/tui/context/theme/nord.json +0 -223
- package/src/cli/cmd/tui/context/theme/one-dark.json +0 -84
- package/src/cli/cmd/tui/context/theme/orng.json +0 -249
- package/src/cli/cmd/tui/context/theme/osaka-jade.json +0 -93
- package/src/cli/cmd/tui/context/theme/palenight.json +0 -222
- package/src/cli/cmd/tui/context/theme/rosepine.json +0 -234
- package/src/cli/cmd/tui/context/theme/solarized.json +0 -223
- package/src/cli/cmd/tui/context/theme/synthwave84.json +0 -226
- package/src/cli/cmd/tui/context/theme/tokyonight.json +0 -243
- package/src/cli/cmd/tui/context/theme/vercel.json +0 -245
- package/src/cli/cmd/tui/context/theme/vesper.json +0 -218
- package/src/cli/cmd/tui/context/theme/zenburn.json +0 -223
- package/src/cli/cmd/tui/context/theme.tsx +0 -1152
- package/src/cli/cmd/tui/event.ts +0 -48
- package/src/cli/cmd/tui/routes/home.tsx +0 -140
- package/src/cli/cmd/tui/routes/session/dialog-fork-from-timeline.tsx +0 -64
- package/src/cli/cmd/tui/routes/session/dialog-message.tsx +0 -109
- package/src/cli/cmd/tui/routes/session/dialog-subagent.tsx +0 -26
- package/src/cli/cmd/tui/routes/session/dialog-timeline.tsx +0 -47
- package/src/cli/cmd/tui/routes/session/footer.tsx +0 -91
- package/src/cli/cmd/tui/routes/session/header.tsx +0 -142
- package/src/cli/cmd/tui/routes/session/index.tsx +0 -2048
- package/src/cli/cmd/tui/routes/session/permission.tsx +0 -508
- package/src/cli/cmd/tui/routes/session/question.tsx +0 -453
- package/src/cli/cmd/tui/routes/session/sidebar.tsx +0 -313
- package/src/cli/cmd/tui/thread.ts +0 -165
- package/src/cli/cmd/tui/ui/dialog-alert.tsx +0 -57
- package/src/cli/cmd/tui/ui/dialog-confirm.tsx +0 -83
- package/src/cli/cmd/tui/ui/dialog-export-options.tsx +0 -204
- package/src/cli/cmd/tui/ui/dialog-help.tsx +0 -38
- package/src/cli/cmd/tui/ui/dialog-prompt.tsx +0 -77
- package/src/cli/cmd/tui/ui/dialog-select.tsx +0 -385
- package/src/cli/cmd/tui/ui/dialog.tsx +0 -167
- package/src/cli/cmd/tui/ui/link.tsx +0 -28
- package/src/cli/cmd/tui/ui/spinner.ts +0 -368
- package/src/cli/cmd/tui/ui/toast.tsx +0 -100
- package/src/cli/cmd/tui/util/clipboard.ts +0 -160
- package/src/cli/cmd/tui/util/editor.ts +0 -32
- package/src/cli/cmd/tui/util/signal.ts +0 -7
- package/src/cli/cmd/tui/util/terminal.ts +0 -114
- package/src/cli/cmd/tui/util/transcript.ts +0 -98
- package/src/cli/cmd/tui/worker.ts +0 -152
- package/src/cli/cmd/uninstall.ts +0 -357
- package/src/cli/cmd/upgrade.ts +0 -73
- package/src/cli/cmd/web.ts +0 -81
- package/src/cli/error.ts +0 -57
- package/src/cli/network.ts +0 -53
- package/src/cli/ui.ts +0 -86
- package/src/cli/upgrade.ts +0 -25
- package/src/command/index.ts +0 -173
- package/src/command/template/bloxy-resume.txt +0 -15
- package/src/command/template/bloxy-status.txt +0 -25
- package/src/command/template/bloxy-validate.txt +0 -22
- package/src/command/template/bloxy.txt +0 -14
- package/src/command/template/initialize.txt +0 -10
- package/src/command/template/review.txt +0 -99
- package/src/config/config.ts +0 -1367
- package/src/config/markdown.ts +0 -93
- package/src/env/index.ts +0 -26
- package/src/file/ignore.ts +0 -83
- package/src/file/index.ts +0 -415
- package/src/file/ripgrep.ts +0 -407
- package/src/file/time.ts +0 -69
- package/src/file/watcher.ts +0 -127
- package/src/flag/flag.ts +0 -79
- package/src/format/formatter.ts +0 -357
- package/src/format/index.ts +0 -137
- package/src/global/index.ts +0 -55
- package/src/id/id.ts +0 -83
- package/src/ide/index.ts +0 -76
- package/src/index.ts +0 -159
- package/src/installation/index.ts +0 -246
- package/src/lsp/client.ts +0 -252
- package/src/lsp/index.ts +0 -485
- package/src/lsp/language.ts +0 -119
- package/src/lsp/server.ts +0 -2046
- package/src/mcp/auth.ts +0 -135
- package/src/mcp/index.ts +0 -934
- package/src/mcp/oauth-callback.ts +0 -200
- package/src/mcp/oauth-provider.ts +0 -154
- package/src/patch/index.ts +0 -680
- package/src/permission/arity.ts +0 -163
- package/src/permission/index.ts +0 -210
- package/src/permission/next.ts +0 -280
- package/src/plugin/antigravity.ts +0 -378
- package/src/plugin/codex.ts +0 -506
- package/src/plugin/copilot.ts +0 -298
- package/src/plugin/index.ts +0 -136
- package/src/project/bootstrap.ts +0 -35
- package/src/project/instance.ts +0 -91
- package/src/project/project.ts +0 -371
- package/src/project/state.ts +0 -66
- package/src/project/vcs.ts +0 -76
- package/src/provider/auth.ts +0 -147
- package/src/provider/models-snapshot.ts +0 -2
- package/src/provider/models.ts +0 -133
- package/src/provider/provider.ts +0 -1241
- package/src/provider/sdk/openai-compatible/src/README.md +0 -5
- package/src/provider/sdk/openai-compatible/src/index.ts +0 -2
- package/src/provider/sdk/openai-compatible/src/openai-compatible-provider.ts +0 -100
- package/src/provider/sdk/openai-compatible/src/responses/convert-to-openai-responses-input.ts +0 -303
- package/src/provider/sdk/openai-compatible/src/responses/map-openai-responses-finish-reason.ts +0 -22
- package/src/provider/sdk/openai-compatible/src/responses/openai-config.ts +0 -18
- package/src/provider/sdk/openai-compatible/src/responses/openai-error.ts +0 -22
- package/src/provider/sdk/openai-compatible/src/responses/openai-responses-api-types.ts +0 -207
- package/src/provider/sdk/openai-compatible/src/responses/openai-responses-language-model.ts +0 -1732
- package/src/provider/sdk/openai-compatible/src/responses/openai-responses-prepare-tools.ts +0 -177
- package/src/provider/sdk/openai-compatible/src/responses/openai-responses-settings.ts +0 -1
- package/src/provider/sdk/openai-compatible/src/responses/tool/code-interpreter.ts +0 -88
- package/src/provider/sdk/openai-compatible/src/responses/tool/file-search.ts +0 -128
- package/src/provider/sdk/openai-compatible/src/responses/tool/image-generation.ts +0 -115
- package/src/provider/sdk/openai-compatible/src/responses/tool/local-shell.ts +0 -65
- package/src/provider/sdk/openai-compatible/src/responses/tool/web-search-preview.ts +0 -104
- package/src/provider/sdk/openai-compatible/src/responses/tool/web-search.ts +0 -103
- package/src/provider/transform.ts +0 -741
- package/src/pty/index.ts +0 -241
- package/src/question/index.ts +0 -171
- package/src/scheduler/index.ts +0 -61
- package/src/server/error.ts +0 -36
- package/src/server/event.ts +0 -7
- package/src/server/mdns.ts +0 -59
- package/src/server/routes/config.ts +0 -92
- package/src/server/routes/experimental.ts +0 -208
- package/src/server/routes/file.ts +0 -197
- package/src/server/routes/global.ts +0 -135
- package/src/server/routes/mcp.ts +0 -225
- package/src/server/routes/permission.ts +0 -68
- package/src/server/routes/project.ts +0 -82
- package/src/server/routes/provider.ts +0 -165
- package/src/server/routes/pty.ts +0 -169
- package/src/server/routes/question.ts +0 -98
- package/src/server/routes/session.ts +0 -939
- package/src/server/routes/tui.ts +0 -379
- package/src/server/server.ts +0 -604
- package/src/session/compaction.ts +0 -225
- package/src/session/fallback.ts +0 -246
- package/src/session/index.ts +0 -498
- package/src/session/instruction.ts +0 -164
- package/src/session/llm.ts +0 -298
- package/src/session/message-v2.ts +0 -747
- package/src/session/message.ts +0 -189
- package/src/session/processor.ts +0 -450
- package/src/session/prompt/anthropic-20250930.txt +0 -166
- package/src/session/prompt/anthropic.txt +0 -105
- package/src/session/prompt/beast.txt +0 -147
- package/src/session/prompt/build-switch.txt +0 -5
- package/src/session/prompt/codex_header.txt +0 -79
- package/src/session/prompt/copilot-gpt-5.txt +0 -143
- package/src/session/prompt/gemini.txt +0 -155
- package/src/session/prompt/max-steps.txt +0 -16
- package/src/session/prompt/plan-reminder-anthropic.txt +0 -67
- package/src/session/prompt/plan.txt +0 -26
- package/src/session/prompt/qwen.txt +0 -109
- package/src/session/prompt.ts +0 -1822
- package/src/session/retry.ts +0 -99
- package/src/session/revert.ts +0 -121
- package/src/session/status.ts +0 -100
- package/src/session/summary.ts +0 -217
- package/src/session/system.ts +0 -52
- package/src/session/todo.ts +0 -37
- package/src/share/share-next.ts +0 -200
- package/src/share/share.ts +0 -92
- package/src/shell/shell.ts +0 -67
- package/src/skill/index.ts +0 -1
- package/src/skill/skill.ts +0 -135
- package/src/snapshot/index.ts +0 -236
- package/src/storage/storage.ts +0 -227
- package/src/tool/apply_patch.ts +0 -281
- package/src/tool/apply_patch.txt +0 -33
- package/src/tool/bash.ts +0 -258
- package/src/tool/bash.txt +0 -115
- package/src/tool/batch.ts +0 -175
- package/src/tool/batch.txt +0 -24
- package/src/tool/bloxy-control.ts +0 -123
- package/src/tool/bloxy-control.txt +0 -13
- package/src/tool/codesearch.ts +0 -132
- package/src/tool/codesearch.txt +0 -12
- package/src/tool/edit.ts +0 -655
- package/src/tool/edit.txt +0 -10
- package/src/tool/external-directory.ts +0 -32
- package/src/tool/glob.ts +0 -77
- package/src/tool/glob.txt +0 -6
- package/src/tool/grep.ts +0 -154
- package/src/tool/grep.txt +0 -8
- package/src/tool/invalid.ts +0 -17
- package/src/tool/ls.ts +0 -121
- package/src/tool/ls.txt +0 -1
- package/src/tool/lsp.ts +0 -96
- package/src/tool/lsp.txt +0 -19
- package/src/tool/multiedit.ts +0 -46
- package/src/tool/multiedit.txt +0 -41
- package/src/tool/plan-enter.txt +0 -14
- package/src/tool/plan-exit.txt +0 -13
- package/src/tool/plan.ts +0 -130
- package/src/tool/question.ts +0 -33
- package/src/tool/question.txt +0 -10
- package/src/tool/read.ts +0 -211
- package/src/tool/read.txt +0 -12
- package/src/tool/registry.ts +0 -161
- package/src/tool/skill.ts +0 -82
- package/src/tool/task.ts +0 -191
- package/src/tool/task.txt +0 -60
- package/src/tool/todo.ts +0 -53
- package/src/tool/todoread.txt +0 -14
- package/src/tool/todowrite.txt +0 -167
- package/src/tool/tool.ts +0 -89
- package/src/tool/truncation.ts +0 -106
- package/src/tool/webfetch.ts +0 -188
- package/src/tool/webfetch.txt +0 -13
- package/src/tool/websearch.ts +0 -150
- package/src/tool/websearch.txt +0 -14
- package/src/tool/write.ts +0 -85
- package/src/tool/write.txt +0 -8
- package/src/util/archive.ts +0 -16
- package/src/util/binary.ts +0 -41
- package/src/util/color.ts +0 -19
- package/src/util/context.ts +0 -25
- package/src/util/defer.ts +0 -12
- package/src/util/error.ts +0 -54
- package/src/util/eventloop.ts +0 -20
- package/src/util/filesystem.ts +0 -93
- package/src/util/fn.ts +0 -11
- package/src/util/format.ts +0 -20
- package/src/util/iife.ts +0 -3
- package/src/util/keybind.ts +0 -103
- package/src/util/lazy.ts +0 -23
- package/src/util/locale.ts +0 -81
- package/src/util/lock.ts +0 -98
- package/src/util/log.ts +0 -180
- package/src/util/queue.ts +0 -32
- package/src/util/rpc.ts +0 -66
- package/src/util/scrap.ts +0 -10
- package/src/util/signal.ts +0 -12
- package/src/util/slug.ts +0 -74
- package/src/util/timeout.ts +0 -14
- package/src/util/token.ts +0 -7
- package/src/util/wildcard.ts +0 -56
- package/src/worktree/index.ts +0 -549
package/src/util/filesystem.ts
DELETED
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
import { realpathSync } from "fs"
|
|
2
|
-
import { dirname, join, relative } from "path"
|
|
3
|
-
|
|
4
|
-
export namespace Filesystem {
|
|
5
|
-
export const exists = (p: string) =>
|
|
6
|
-
Bun.file(p)
|
|
7
|
-
.stat()
|
|
8
|
-
.then(() => true)
|
|
9
|
-
.catch(() => false)
|
|
10
|
-
|
|
11
|
-
export const isDir = (p: string) =>
|
|
12
|
-
Bun.file(p)
|
|
13
|
-
.stat()
|
|
14
|
-
.then((s) => s.isDirectory())
|
|
15
|
-
.catch(() => false)
|
|
16
|
-
/**
|
|
17
|
-
* On Windows, normalize a path to its canonical casing using the filesystem.
|
|
18
|
-
* This is needed because Windows paths are case-insensitive but LSP servers
|
|
19
|
-
* may return paths with different casing than what we send them.
|
|
20
|
-
*/
|
|
21
|
-
export function normalizePath(p: string): string {
|
|
22
|
-
if (process.platform !== "win32") return p
|
|
23
|
-
try {
|
|
24
|
-
return realpathSync.native(p)
|
|
25
|
-
} catch {
|
|
26
|
-
return p
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
export function overlaps(a: string, b: string) {
|
|
30
|
-
const relA = relative(a, b)
|
|
31
|
-
const relB = relative(b, a)
|
|
32
|
-
return !relA || !relA.startsWith("..") || !relB || !relB.startsWith("..")
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export function contains(parent: string, child: string) {
|
|
36
|
-
return !relative(parent, child).startsWith("..")
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export async function findUp(target: string, start: string, stop?: string) {
|
|
40
|
-
let current = start
|
|
41
|
-
const result = []
|
|
42
|
-
while (true) {
|
|
43
|
-
const search = join(current, target)
|
|
44
|
-
if (await exists(search)) result.push(search)
|
|
45
|
-
if (stop === current) break
|
|
46
|
-
const parent = dirname(current)
|
|
47
|
-
if (parent === current) break
|
|
48
|
-
current = parent
|
|
49
|
-
}
|
|
50
|
-
return result
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export async function* up(options: { targets: string[]; start: string; stop?: string }) {
|
|
54
|
-
const { targets, start, stop } = options
|
|
55
|
-
let current = start
|
|
56
|
-
while (true) {
|
|
57
|
-
for (const target of targets) {
|
|
58
|
-
const search = join(current, target)
|
|
59
|
-
if (await exists(search)) yield search
|
|
60
|
-
}
|
|
61
|
-
if (stop === current) break
|
|
62
|
-
const parent = dirname(current)
|
|
63
|
-
if (parent === current) break
|
|
64
|
-
current = parent
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export async function globUp(pattern: string, start: string, stop?: string) {
|
|
69
|
-
let current = start
|
|
70
|
-
const result = []
|
|
71
|
-
while (true) {
|
|
72
|
-
try {
|
|
73
|
-
const glob = new Bun.Glob(pattern)
|
|
74
|
-
for await (const match of glob.scan({
|
|
75
|
-
cwd: current,
|
|
76
|
-
absolute: true,
|
|
77
|
-
onlyFiles: true,
|
|
78
|
-
followSymlinks: true,
|
|
79
|
-
dot: true,
|
|
80
|
-
})) {
|
|
81
|
-
result.push(match)
|
|
82
|
-
}
|
|
83
|
-
} catch {
|
|
84
|
-
// Skip invalid glob patterns
|
|
85
|
-
}
|
|
86
|
-
if (stop === current) break
|
|
87
|
-
const parent = dirname(current)
|
|
88
|
-
if (parent === current) break
|
|
89
|
-
current = parent
|
|
90
|
-
}
|
|
91
|
-
return result
|
|
92
|
-
}
|
|
93
|
-
}
|
package/src/util/fn.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { z } from "zod"
|
|
2
|
-
|
|
3
|
-
export function fn<T extends z.ZodType, Result>(schema: T, cb: (input: z.infer<T>) => Result) {
|
|
4
|
-
const result = (input: z.infer<T>) => {
|
|
5
|
-
const parsed = schema.parse(input)
|
|
6
|
-
return cb(parsed)
|
|
7
|
-
}
|
|
8
|
-
result.force = (input: z.infer<T>) => cb(input)
|
|
9
|
-
result.schema = schema
|
|
10
|
-
return result
|
|
11
|
-
}
|
package/src/util/format.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
export function formatDuration(secs: number) {
|
|
2
|
-
if (secs <= 0) return ""
|
|
3
|
-
if (secs < 60) return `${secs}s`
|
|
4
|
-
if (secs < 3600) {
|
|
5
|
-
const mins = Math.floor(secs / 60)
|
|
6
|
-
const remaining = secs % 60
|
|
7
|
-
return remaining > 0 ? `${mins}m ${remaining}s` : `${mins}m`
|
|
8
|
-
}
|
|
9
|
-
if (secs < 86400) {
|
|
10
|
-
const hours = Math.floor(secs / 3600)
|
|
11
|
-
const remaining = Math.floor((secs % 3600) / 60)
|
|
12
|
-
return remaining > 0 ? `${hours}h ${remaining}m` : `${hours}h`
|
|
13
|
-
}
|
|
14
|
-
if (secs < 604800) {
|
|
15
|
-
const days = Math.floor(secs / 86400)
|
|
16
|
-
return days === 1 ? "~1 day" : `~${days} days`
|
|
17
|
-
}
|
|
18
|
-
const weeks = Math.floor(secs / 604800)
|
|
19
|
-
return weeks === 1 ? "~1 week" : `~${weeks} weeks`
|
|
20
|
-
}
|
package/src/util/iife.ts
DELETED
package/src/util/keybind.ts
DELETED
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
import { isDeepEqual } from "remeda"
|
|
2
|
-
import type { ParsedKey } from "@opentui/core"
|
|
3
|
-
|
|
4
|
-
export namespace Keybind {
|
|
5
|
-
/**
|
|
6
|
-
* Keybind info derived from OpenTUI's ParsedKey with our custom `leader` field.
|
|
7
|
-
* This ensures type compatibility and catches missing fields at compile time.
|
|
8
|
-
*/
|
|
9
|
-
export type Info = Pick<ParsedKey, "name" | "ctrl" | "meta" | "shift" | "super"> & {
|
|
10
|
-
leader: boolean // our custom field
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export function match(a: Info | undefined, b: Info): boolean {
|
|
14
|
-
if (!a) return false
|
|
15
|
-
const normalizedA = { ...a, super: a.super ?? false }
|
|
16
|
-
const normalizedB = { ...b, super: b.super ?? false }
|
|
17
|
-
return isDeepEqual(normalizedA, normalizedB)
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Convert OpenTUI's ParsedKey to our Keybind.Info format.
|
|
22
|
-
* This helper ensures all required fields are present and avoids manual object creation.
|
|
23
|
-
*/
|
|
24
|
-
export function fromParsedKey(key: ParsedKey, leader = false): Info {
|
|
25
|
-
return {
|
|
26
|
-
name: key.name,
|
|
27
|
-
ctrl: key.ctrl,
|
|
28
|
-
meta: key.meta,
|
|
29
|
-
shift: key.shift,
|
|
30
|
-
super: key.super ?? false,
|
|
31
|
-
leader,
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export function toString(info: Info | undefined): string {
|
|
36
|
-
if (!info) return ""
|
|
37
|
-
const parts: string[] = []
|
|
38
|
-
|
|
39
|
-
if (info.ctrl) parts.push("ctrl")
|
|
40
|
-
if (info.meta) parts.push("alt")
|
|
41
|
-
if (info.super) parts.push("super")
|
|
42
|
-
if (info.shift) parts.push("shift")
|
|
43
|
-
if (info.name) {
|
|
44
|
-
if (info.name === "delete") parts.push("del")
|
|
45
|
-
else parts.push(info.name)
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
let result = parts.join("+")
|
|
49
|
-
|
|
50
|
-
if (info.leader) {
|
|
51
|
-
result = result ? `<leader> ${result}` : `<leader>`
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return result
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export function parse(key: string): Info[] {
|
|
58
|
-
if (key === "none") return []
|
|
59
|
-
|
|
60
|
-
return key.split(",").map((combo) => {
|
|
61
|
-
// Handle <leader> syntax by replacing with leader+
|
|
62
|
-
const normalized = combo.replace(/<leader>/g, "leader+")
|
|
63
|
-
const parts = normalized.toLowerCase().split("+")
|
|
64
|
-
const info: Info = {
|
|
65
|
-
ctrl: false,
|
|
66
|
-
meta: false,
|
|
67
|
-
shift: false,
|
|
68
|
-
leader: false,
|
|
69
|
-
name: "",
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
for (const part of parts) {
|
|
73
|
-
switch (part) {
|
|
74
|
-
case "ctrl":
|
|
75
|
-
info.ctrl = true
|
|
76
|
-
break
|
|
77
|
-
case "alt":
|
|
78
|
-
case "meta":
|
|
79
|
-
case "option":
|
|
80
|
-
info.meta = true
|
|
81
|
-
break
|
|
82
|
-
case "super":
|
|
83
|
-
info.super = true
|
|
84
|
-
break
|
|
85
|
-
case "shift":
|
|
86
|
-
info.shift = true
|
|
87
|
-
break
|
|
88
|
-
case "leader":
|
|
89
|
-
info.leader = true
|
|
90
|
-
break
|
|
91
|
-
case "esc":
|
|
92
|
-
info.name = "escape"
|
|
93
|
-
break
|
|
94
|
-
default:
|
|
95
|
-
info.name = part
|
|
96
|
-
break
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
return info
|
|
101
|
-
})
|
|
102
|
-
}
|
|
103
|
-
}
|
package/src/util/lazy.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
export interface LazyFunction<T> {
|
|
2
|
-
(): T
|
|
3
|
-
reset(): void
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
export function lazy<T>(fn: () => T): LazyFunction<T> {
|
|
7
|
-
let value: T | undefined
|
|
8
|
-
let loaded = false
|
|
9
|
-
|
|
10
|
-
const result = (): T => {
|
|
11
|
-
if (loaded) return value as T
|
|
12
|
-
loaded = true
|
|
13
|
-
value = fn()
|
|
14
|
-
return value as T
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
result.reset = () => {
|
|
18
|
-
loaded = false
|
|
19
|
-
value = undefined
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
return result
|
|
23
|
-
}
|
package/src/util/locale.ts
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
export namespace Locale {
|
|
2
|
-
export function titlecase(str: string) {
|
|
3
|
-
return str.replace(/\b\w/g, (c) => c.toUpperCase())
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
export function time(input: number): string {
|
|
7
|
-
const date = new Date(input)
|
|
8
|
-
return date.toLocaleTimeString(undefined, { timeStyle: "short" })
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export function datetime(input: number): string {
|
|
12
|
-
const date = new Date(input)
|
|
13
|
-
const localTime = time(input)
|
|
14
|
-
const localDate = date.toLocaleDateString()
|
|
15
|
-
return `${localTime} · ${localDate}`
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export function todayTimeOrDateTime(input: number): string {
|
|
19
|
-
const date = new Date(input)
|
|
20
|
-
const now = new Date()
|
|
21
|
-
const isToday =
|
|
22
|
-
date.getFullYear() === now.getFullYear() && date.getMonth() === now.getMonth() && date.getDate() === now.getDate()
|
|
23
|
-
|
|
24
|
-
if (isToday) {
|
|
25
|
-
return time(input)
|
|
26
|
-
} else {
|
|
27
|
-
return datetime(input)
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export function number(num: number): string {
|
|
32
|
-
if (num >= 1000000) {
|
|
33
|
-
return (num / 1000000).toFixed(1) + "M"
|
|
34
|
-
} else if (num >= 1000) {
|
|
35
|
-
return (num / 1000).toFixed(1) + "K"
|
|
36
|
-
}
|
|
37
|
-
return num.toString()
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export function duration(input: number) {
|
|
41
|
-
if (input < 1000) {
|
|
42
|
-
return `${input}ms`
|
|
43
|
-
}
|
|
44
|
-
if (input < 60000) {
|
|
45
|
-
return `${(input / 1000).toFixed(1)}s`
|
|
46
|
-
}
|
|
47
|
-
if (input < 3600000) {
|
|
48
|
-
const minutes = Math.floor(input / 60000)
|
|
49
|
-
const seconds = Math.floor((input % 60000) / 1000)
|
|
50
|
-
return `${minutes}m ${seconds}s`
|
|
51
|
-
}
|
|
52
|
-
if (input < 86400000) {
|
|
53
|
-
const hours = Math.floor(input / 3600000)
|
|
54
|
-
const minutes = Math.floor((input % 3600000) / 60000)
|
|
55
|
-
return `${hours}h ${minutes}m`
|
|
56
|
-
}
|
|
57
|
-
const hours = Math.floor(input / 3600000)
|
|
58
|
-
const days = Math.floor((input % 3600000) / 86400000)
|
|
59
|
-
return `${days}d ${hours}h`
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export function truncate(str: string, len: number): string {
|
|
63
|
-
if (str.length <= len) return str
|
|
64
|
-
return str.slice(0, len - 1) + "…"
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
export function truncateMiddle(str: string, maxLength: number = 35): string {
|
|
68
|
-
if (str.length <= maxLength) return str
|
|
69
|
-
|
|
70
|
-
const ellipsis = "…"
|
|
71
|
-
const keepStart = Math.ceil((maxLength - ellipsis.length) / 2)
|
|
72
|
-
const keepEnd = Math.floor((maxLength - ellipsis.length) / 2)
|
|
73
|
-
|
|
74
|
-
return str.slice(0, keepStart) + ellipsis + str.slice(-keepEnd)
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
export function pluralize(count: number, singular: string, plural: string): string {
|
|
78
|
-
const template = count === 1 ? singular : plural
|
|
79
|
-
return template.replace("{}", count.toString())
|
|
80
|
-
}
|
|
81
|
-
}
|
package/src/util/lock.ts
DELETED
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
export namespace Lock {
|
|
2
|
-
const locks = new Map<
|
|
3
|
-
string,
|
|
4
|
-
{
|
|
5
|
-
readers: number
|
|
6
|
-
writer: boolean
|
|
7
|
-
waitingReaders: (() => void)[]
|
|
8
|
-
waitingWriters: (() => void)[]
|
|
9
|
-
}
|
|
10
|
-
>()
|
|
11
|
-
|
|
12
|
-
function get(key: string) {
|
|
13
|
-
if (!locks.has(key)) {
|
|
14
|
-
locks.set(key, {
|
|
15
|
-
readers: 0,
|
|
16
|
-
writer: false,
|
|
17
|
-
waitingReaders: [],
|
|
18
|
-
waitingWriters: [],
|
|
19
|
-
})
|
|
20
|
-
}
|
|
21
|
-
return locks.get(key)!
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function process(key: string) {
|
|
25
|
-
const lock = locks.get(key)
|
|
26
|
-
if (!lock || lock.writer || lock.readers > 0) return
|
|
27
|
-
|
|
28
|
-
// Prioritize writers to prevent starvation
|
|
29
|
-
if (lock.waitingWriters.length > 0) {
|
|
30
|
-
const nextWriter = lock.waitingWriters.shift()!
|
|
31
|
-
nextWriter()
|
|
32
|
-
return
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// Wake up all waiting readers
|
|
36
|
-
while (lock.waitingReaders.length > 0) {
|
|
37
|
-
const nextReader = lock.waitingReaders.shift()!
|
|
38
|
-
nextReader()
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// Clean up empty locks
|
|
42
|
-
if (lock.readers === 0 && !lock.writer && lock.waitingReaders.length === 0 && lock.waitingWriters.length === 0) {
|
|
43
|
-
locks.delete(key)
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export async function read(key: string): Promise<Disposable> {
|
|
48
|
-
const lock = get(key)
|
|
49
|
-
|
|
50
|
-
return new Promise((resolve) => {
|
|
51
|
-
if (!lock.writer && lock.waitingWriters.length === 0) {
|
|
52
|
-
lock.readers++
|
|
53
|
-
resolve({
|
|
54
|
-
[Symbol.dispose]: () => {
|
|
55
|
-
lock.readers--
|
|
56
|
-
process(key)
|
|
57
|
-
},
|
|
58
|
-
})
|
|
59
|
-
} else {
|
|
60
|
-
lock.waitingReaders.push(() => {
|
|
61
|
-
lock.readers++
|
|
62
|
-
resolve({
|
|
63
|
-
[Symbol.dispose]: () => {
|
|
64
|
-
lock.readers--
|
|
65
|
-
process(key)
|
|
66
|
-
},
|
|
67
|
-
})
|
|
68
|
-
})
|
|
69
|
-
}
|
|
70
|
-
})
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export async function write(key: string): Promise<Disposable> {
|
|
74
|
-
const lock = get(key)
|
|
75
|
-
|
|
76
|
-
return new Promise((resolve) => {
|
|
77
|
-
if (!lock.writer && lock.readers === 0) {
|
|
78
|
-
lock.writer = true
|
|
79
|
-
resolve({
|
|
80
|
-
[Symbol.dispose]: () => {
|
|
81
|
-
lock.writer = false
|
|
82
|
-
process(key)
|
|
83
|
-
},
|
|
84
|
-
})
|
|
85
|
-
} else {
|
|
86
|
-
lock.waitingWriters.push(() => {
|
|
87
|
-
lock.writer = true
|
|
88
|
-
resolve({
|
|
89
|
-
[Symbol.dispose]: () => {
|
|
90
|
-
lock.writer = false
|
|
91
|
-
process(key)
|
|
92
|
-
},
|
|
93
|
-
})
|
|
94
|
-
})
|
|
95
|
-
}
|
|
96
|
-
})
|
|
97
|
-
}
|
|
98
|
-
}
|
package/src/util/log.ts
DELETED
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
import path from "path"
|
|
2
|
-
import fs from "fs/promises"
|
|
3
|
-
import { Global } from "../global"
|
|
4
|
-
import z from "zod"
|
|
5
|
-
|
|
6
|
-
export namespace Log {
|
|
7
|
-
export const Level = z.enum(["DEBUG", "INFO", "WARN", "ERROR"]).meta({ ref: "LogLevel", description: "Log level" })
|
|
8
|
-
export type Level = z.infer<typeof Level>
|
|
9
|
-
|
|
10
|
-
const levelPriority: Record<Level, number> = {
|
|
11
|
-
DEBUG: 0,
|
|
12
|
-
INFO: 1,
|
|
13
|
-
WARN: 2,
|
|
14
|
-
ERROR: 3,
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
let level: Level = "INFO"
|
|
18
|
-
|
|
19
|
-
function shouldLog(input: Level): boolean {
|
|
20
|
-
return levelPriority[input] >= levelPriority[level]
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export type Logger = {
|
|
24
|
-
debug(message?: any, extra?: Record<string, any>): void
|
|
25
|
-
info(message?: any, extra?: Record<string, any>): void
|
|
26
|
-
error(message?: any, extra?: Record<string, any>): void
|
|
27
|
-
warn(message?: any, extra?: Record<string, any>): void
|
|
28
|
-
tag(key: string, value: string): Logger
|
|
29
|
-
clone(): Logger
|
|
30
|
-
time(
|
|
31
|
-
message: string,
|
|
32
|
-
extra?: Record<string, any>,
|
|
33
|
-
): {
|
|
34
|
-
stop(): void
|
|
35
|
-
[Symbol.dispose](): void
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const loggers = new Map<string, Logger>()
|
|
40
|
-
|
|
41
|
-
export const Default = create({ service: "default" })
|
|
42
|
-
|
|
43
|
-
export interface Options {
|
|
44
|
-
print: boolean
|
|
45
|
-
dev?: boolean
|
|
46
|
-
level?: Level
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
let logpath = ""
|
|
50
|
-
export function file() {
|
|
51
|
-
return logpath
|
|
52
|
-
}
|
|
53
|
-
let write = (msg: any) => {
|
|
54
|
-
process.stderr.write(msg)
|
|
55
|
-
return msg.length
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export async function init(options: Options) {
|
|
59
|
-
if (options.level) level = options.level
|
|
60
|
-
cleanup(Global.Path.log)
|
|
61
|
-
if (options.print) return
|
|
62
|
-
logpath = path.join(
|
|
63
|
-
Global.Path.log,
|
|
64
|
-
options.dev ? "dev.log" : new Date().toISOString().split(".")[0].replace(/:/g, "") + ".log",
|
|
65
|
-
)
|
|
66
|
-
const logfile = Bun.file(logpath)
|
|
67
|
-
await fs.truncate(logpath).catch(() => {})
|
|
68
|
-
const writer = logfile.writer()
|
|
69
|
-
write = async (msg: any) => {
|
|
70
|
-
const num = writer.write(msg)
|
|
71
|
-
writer.flush()
|
|
72
|
-
return num
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
async function cleanup(dir: string) {
|
|
77
|
-
const glob = new Bun.Glob("????-??-??T??????.log")
|
|
78
|
-
const files = await Array.fromAsync(
|
|
79
|
-
glob.scan({
|
|
80
|
-
cwd: dir,
|
|
81
|
-
absolute: true,
|
|
82
|
-
}),
|
|
83
|
-
)
|
|
84
|
-
if (files.length <= 5) return
|
|
85
|
-
|
|
86
|
-
const filesToDelete = files.slice(0, -10)
|
|
87
|
-
await Promise.all(filesToDelete.map((file) => fs.unlink(file).catch(() => {})))
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
function formatError(error: Error, depth = 0): string {
|
|
91
|
-
const result = error.message
|
|
92
|
-
return error.cause instanceof Error && depth < 10
|
|
93
|
-
? result + " Caused by: " + formatError(error.cause, depth + 1)
|
|
94
|
-
: result
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
let last = Date.now()
|
|
98
|
-
export function create(tags?: Record<string, any>) {
|
|
99
|
-
tags = tags || {}
|
|
100
|
-
|
|
101
|
-
const service = tags["service"]
|
|
102
|
-
if (service && typeof service === "string") {
|
|
103
|
-
const cached = loggers.get(service)
|
|
104
|
-
if (cached) {
|
|
105
|
-
return cached
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
function build(message: any, extra?: Record<string, any>) {
|
|
110
|
-
const prefix = Object.entries({
|
|
111
|
-
...tags,
|
|
112
|
-
...extra,
|
|
113
|
-
})
|
|
114
|
-
.filter(([_, value]) => value !== undefined && value !== null)
|
|
115
|
-
.map(([key, value]) => {
|
|
116
|
-
const prefix = `${key}=`
|
|
117
|
-
if (value instanceof Error) return prefix + formatError(value)
|
|
118
|
-
if (typeof value === "object") return prefix + JSON.stringify(value)
|
|
119
|
-
return prefix + value
|
|
120
|
-
})
|
|
121
|
-
.join(" ")
|
|
122
|
-
const next = new Date()
|
|
123
|
-
const diff = next.getTime() - last
|
|
124
|
-
last = next.getTime()
|
|
125
|
-
return [next.toISOString().split(".")[0], "+" + diff + "ms", prefix, message].filter(Boolean).join(" ") + "\n"
|
|
126
|
-
}
|
|
127
|
-
const result: Logger = {
|
|
128
|
-
debug(message?: any, extra?: Record<string, any>) {
|
|
129
|
-
if (shouldLog("DEBUG")) {
|
|
130
|
-
write("DEBUG " + build(message, extra))
|
|
131
|
-
}
|
|
132
|
-
},
|
|
133
|
-
info(message?: any, extra?: Record<string, any>) {
|
|
134
|
-
if (shouldLog("INFO")) {
|
|
135
|
-
write("INFO " + build(message, extra))
|
|
136
|
-
}
|
|
137
|
-
},
|
|
138
|
-
error(message?: any, extra?: Record<string, any>) {
|
|
139
|
-
if (shouldLog("ERROR")) {
|
|
140
|
-
write("ERROR " + build(message, extra))
|
|
141
|
-
}
|
|
142
|
-
},
|
|
143
|
-
warn(message?: any, extra?: Record<string, any>) {
|
|
144
|
-
if (shouldLog("WARN")) {
|
|
145
|
-
write("WARN " + build(message, extra))
|
|
146
|
-
}
|
|
147
|
-
},
|
|
148
|
-
tag(key: string, value: string) {
|
|
149
|
-
if (tags) tags[key] = value
|
|
150
|
-
return result
|
|
151
|
-
},
|
|
152
|
-
clone() {
|
|
153
|
-
return Log.create({ ...tags })
|
|
154
|
-
},
|
|
155
|
-
time(message: string, extra?: Record<string, any>) {
|
|
156
|
-
const now = Date.now()
|
|
157
|
-
result.info(message, { status: "started", ...extra })
|
|
158
|
-
function stop() {
|
|
159
|
-
result.info(message, {
|
|
160
|
-
status: "completed",
|
|
161
|
-
duration: Date.now() - now,
|
|
162
|
-
...extra,
|
|
163
|
-
})
|
|
164
|
-
}
|
|
165
|
-
return {
|
|
166
|
-
stop,
|
|
167
|
-
[Symbol.dispose]() {
|
|
168
|
-
stop()
|
|
169
|
-
},
|
|
170
|
-
}
|
|
171
|
-
},
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
if (service && typeof service === "string") {
|
|
175
|
-
loggers.set(service, result)
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
return result
|
|
179
|
-
}
|
|
180
|
-
}
|
package/src/util/queue.ts
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
export class AsyncQueue<T> implements AsyncIterable<T> {
|
|
2
|
-
private queue: T[] = []
|
|
3
|
-
private resolvers: ((value: T) => void)[] = []
|
|
4
|
-
|
|
5
|
-
push(item: T) {
|
|
6
|
-
const resolve = this.resolvers.shift()
|
|
7
|
-
if (resolve) resolve(item)
|
|
8
|
-
else this.queue.push(item)
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
async next(): Promise<T> {
|
|
12
|
-
if (this.queue.length > 0) return this.queue.shift()!
|
|
13
|
-
return new Promise((resolve) => this.resolvers.push(resolve))
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
async *[Symbol.asyncIterator]() {
|
|
17
|
-
while (true) yield await this.next()
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export async function work<T>(concurrency: number, items: T[], fn: (item: T) => Promise<void>) {
|
|
22
|
-
const pending = [...items]
|
|
23
|
-
await Promise.all(
|
|
24
|
-
Array.from({ length: concurrency }, async () => {
|
|
25
|
-
while (true) {
|
|
26
|
-
const item = pending.pop()
|
|
27
|
-
if (item === undefined) return
|
|
28
|
-
await fn(item)
|
|
29
|
-
}
|
|
30
|
-
}),
|
|
31
|
-
)
|
|
32
|
-
}
|