@pablozaiden/terminatui 0.3.0-beta-1 → 0.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.
- package/package.json +10 -3
- package/src/__tests__/configOnChange.test.ts +63 -0
- package/src/builtins/version.ts +1 -1
- package/src/index.ts +22 -0
- package/src/tui/adapters/ink/InkRenderer.tsx +4 -0
- package/src/tui/adapters/opentui/OpenTuiRenderer.tsx +4 -0
- package/src/tui/adapters/types.ts +1 -0
- package/src/tui/screens/ConfigScreen.tsx +6 -1
- package/src/tui/screens/ResultsScreen.tsx +9 -1
- package/src/tui/screens/RunningScreen.tsx +1 -1
- package/.devcontainer/devcontainer.json +0 -19
- package/.devcontainer/install-prerequisites.sh +0 -49
- package/.github/workflows/copilot-setup-steps.yml +0 -32
- package/.github/workflows/pull-request.yml +0 -27
- package/.github/workflows/release-npm-package.yml +0 -81
- package/AGENTS.md +0 -43
- package/CLAUDE.md +0 -1
- package/bun.lock +0 -321
- package/examples/tui-app/commands/config/app/get.ts +0 -62
- package/examples/tui-app/commands/config/app/index.ts +0 -23
- package/examples/tui-app/commands/config/app/set.ts +0 -96
- package/examples/tui-app/commands/config/index.ts +0 -28
- package/examples/tui-app/commands/config/user/get.ts +0 -61
- package/examples/tui-app/commands/config/user/index.ts +0 -23
- package/examples/tui-app/commands/config/user/set.ts +0 -57
- package/examples/tui-app/commands/greet.ts +0 -78
- package/examples/tui-app/commands/math.ts +0 -111
- package/examples/tui-app/commands/status.ts +0 -86
- package/examples/tui-app/index.ts +0 -38
- package/guides/01-hello-world.md +0 -101
- package/guides/02-adding-options.md +0 -103
- package/guides/03-multiple-commands.md +0 -161
- package/guides/04-subcommands.md +0 -206
- package/guides/05-interactive-tui.md +0 -209
- package/guides/06-config-validation.md +0 -256
- package/guides/07-async-cancellation.md +0 -334
- package/guides/08-complete-application.md +0 -507
- package/guides/README.md +0 -78
- package/tsconfig.json +0 -25
package/package.json
CHANGED
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pablozaiden/terminatui",
|
|
3
|
-
"version": "0.3.0
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Terminal UI and Command Line Application Framework",
|
|
5
5
|
"repository": {
|
|
6
6
|
"url": "https://github.com/PabloZaiden/terminatui"
|
|
7
7
|
},
|
|
8
8
|
"type": "module",
|
|
9
|
-
"
|
|
10
|
-
|
|
9
|
+
"files": [
|
|
10
|
+
"src/**/*"
|
|
11
|
+
],
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./src/index.ts",
|
|
15
|
+
"default": "./src/index.ts"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
11
18
|
"scripts": {
|
|
12
19
|
"build": "bunx tsc --noEmit",
|
|
13
20
|
"test": "bun test",
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { test, expect } from "bun:test";
|
|
2
|
+
import { Command } from "../core/command.ts";
|
|
3
|
+
import type { OptionSchema } from "../types/command.ts";
|
|
4
|
+
|
|
5
|
+
class TestCommand extends Command<typeof TestCommand.Options> {
|
|
6
|
+
static readonly Options = {
|
|
7
|
+
a: { type: "string" as const, description: "a" },
|
|
8
|
+
b: { type: "string" as const, description: "b" },
|
|
9
|
+
} as const satisfies OptionSchema;
|
|
10
|
+
|
|
11
|
+
readonly name = "my";
|
|
12
|
+
readonly description = "my";
|
|
13
|
+
readonly options = TestCommand.Options;
|
|
14
|
+
|
|
15
|
+
public readonly onChangeCalls: Array<[
|
|
16
|
+
string,
|
|
17
|
+
unknown,
|
|
18
|
+
Record<string, unknown>
|
|
19
|
+
]> = [];
|
|
20
|
+
|
|
21
|
+
override execute(): void {}
|
|
22
|
+
|
|
23
|
+
override onConfigChange(
|
|
24
|
+
key: string,
|
|
25
|
+
value: unknown,
|
|
26
|
+
allValues: Record<string, unknown>
|
|
27
|
+
) {
|
|
28
|
+
this.onChangeCalls.push([key, value, allValues]);
|
|
29
|
+
if (key === "a") {
|
|
30
|
+
return { b: "derived" };
|
|
31
|
+
}
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
applyTuiConfigChange(
|
|
36
|
+
key: string,
|
|
37
|
+
value: unknown,
|
|
38
|
+
values: Record<string, unknown>
|
|
39
|
+
): Record<string, unknown> {
|
|
40
|
+
let nextValues: Record<string, unknown> = { ...values, [key]: value };
|
|
41
|
+
|
|
42
|
+
const updates = this.onConfigChange?.(key, value, nextValues);
|
|
43
|
+
if (updates && typeof updates === "object") {
|
|
44
|
+
nextValues = { ...nextValues, ...updates };
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return nextValues;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
test("onConfigChange merges returned updates", () => {
|
|
52
|
+
const command = new TestCommand();
|
|
53
|
+
|
|
54
|
+
const next = command.applyTuiConfigChange("a", "new", {
|
|
55
|
+
a: "old",
|
|
56
|
+
b: "oldb",
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
expect(command.onChangeCalls.length).toBe(1);
|
|
60
|
+
expect(command.onChangeCalls[0]?.[0]).toBe("a");
|
|
61
|
+
expect(command.onChangeCalls[0]?.[1]).toBe("new");
|
|
62
|
+
expect(next).toEqual({ a: "new", b: "derived" });
|
|
63
|
+
});
|
package/src/builtins/version.ts
CHANGED
|
@@ -18,7 +18,7 @@ interface VersionConfig {
|
|
|
18
18
|
* Format version string with optional commit hash.
|
|
19
19
|
* If commitHash is empty or undefined, shows "(dev)".
|
|
20
20
|
*/
|
|
21
|
-
function formatVersion(version: string, commitHash?: string): string {
|
|
21
|
+
export function formatVersion(version: string, commitHash?: string): string {
|
|
22
22
|
const hashPart = commitHash && commitHash.length > 0
|
|
23
23
|
? commitHash.substring(0, 7)
|
|
24
24
|
: "(dev)";
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export * from "./builtins/help.ts";
|
|
2
|
+
export * from "./builtins/settings.ts";
|
|
3
|
+
export * from "./builtins/version.ts";
|
|
4
|
+
|
|
5
|
+
export * from "./cli/parser.ts";
|
|
6
|
+
export * from "./cli/output/colors.ts";
|
|
7
|
+
|
|
8
|
+
export * from "./core/application.ts";
|
|
9
|
+
export * from "./core/command.ts";
|
|
10
|
+
export * from "./core/context.ts";
|
|
11
|
+
export * from "./core/help.ts";
|
|
12
|
+
export * from "./core/knownCommands.ts";
|
|
13
|
+
export * from "./core/logger.ts";
|
|
14
|
+
export * from "./core/registry.ts";
|
|
15
|
+
|
|
16
|
+
export * from "./tui/TuiApplication.tsx";
|
|
17
|
+
export * from "./tui/TuiRoot.tsx";
|
|
18
|
+
export * from "./tui/registry.ts";
|
|
19
|
+
export * from "./tui/theme.ts";
|
|
20
|
+
export * from "./types/command.ts";
|
|
21
|
+
|
|
22
|
+
export * from "./tui/components/JsonHighlight.tsx";
|
|
@@ -26,6 +26,10 @@ export class InkRenderer implements Renderer {
|
|
|
26
26
|
private instance: ReturnType<typeof render> | null = null;
|
|
27
27
|
private activeKeyboardAdapter: Renderer["keyboard"] | null = null;
|
|
28
28
|
|
|
29
|
+
public supportCustomRendering(): boolean {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
|
|
29
33
|
public keyboard: Renderer["keyboard"] = {
|
|
30
34
|
setActiveHandler: (id, handler) => {
|
|
31
35
|
return this.activeKeyboardAdapter?.setActiveHandler(id, handler) ?? (() => {});
|
|
@@ -27,6 +27,10 @@ export class OpenTuiRenderer implements Renderer {
|
|
|
27
27
|
|
|
28
28
|
private activeKeyboardAdapter: Renderer["keyboard"] | null = null;
|
|
29
29
|
|
|
30
|
+
public supportCustomRendering(): boolean {
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
|
|
30
34
|
public keyboard: Renderer["keyboard"] = {
|
|
31
35
|
setActiveHandler: (id, handler) => {
|
|
32
36
|
return this.activeKeyboardAdapter?.setActiveHandler(id, handler) ?? (() => {});
|
|
@@ -116,7 +116,12 @@ export class ConfigScreen extends ScreenBase {
|
|
|
116
116
|
currentValue: values[fieldKey],
|
|
117
117
|
fieldConfigs: derivedFieldConfigs,
|
|
118
118
|
onSubmit: (value: unknown) => {
|
|
119
|
-
|
|
119
|
+
let nextValues = { ...values, [fieldKey]: value };
|
|
120
|
+
const updates = command.onConfigChange?.(fieldKey, value, nextValues);
|
|
121
|
+
if (updates) {
|
|
122
|
+
nextValues = { ...nextValues, ...updates };
|
|
123
|
+
}
|
|
124
|
+
|
|
120
125
|
navigation.replace<ConfigParams>(ConfigScreen.Id, { ...params, values: nextValues });
|
|
121
126
|
navigation.closeModal();
|
|
122
127
|
},
|
|
@@ -5,6 +5,7 @@ import { ResultsPanel } from "../components/ResultsPanel.tsx";
|
|
|
5
5
|
import { useClipboardProvider } from "../hooks/useClipboardProvider.ts";
|
|
6
6
|
import { type ScreenComponent } from "../registry.ts";
|
|
7
7
|
import { ScreenBase } from "./ScreenBase.ts";
|
|
8
|
+
import { useRenderer } from "../context/RendererContext.tsx";
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Screen state stored in navigation params.
|
|
@@ -36,6 +37,13 @@ export class ResultsScreen extends ScreenBase {
|
|
|
36
37
|
|
|
37
38
|
const { result, command } = params;
|
|
38
39
|
|
|
40
|
+
const renderer = useRenderer();
|
|
41
|
+
|
|
42
|
+
let renderFunction = undefined;
|
|
43
|
+
if (renderer.supportCustomRendering()) {
|
|
44
|
+
renderFunction = command.renderResult;
|
|
45
|
+
}
|
|
46
|
+
|
|
39
47
|
// Register clipboard provider for this screen
|
|
40
48
|
useClipboardProvider(
|
|
41
49
|
useCallback(() => {
|
|
@@ -52,7 +60,7 @@ export class ResultsScreen extends ScreenBase {
|
|
|
52
60
|
result={result as CommandResult | null}
|
|
53
61
|
error={null}
|
|
54
62
|
focused={true}
|
|
55
|
-
renderResult={
|
|
63
|
+
renderResult={renderFunction}
|
|
56
64
|
/>
|
|
57
65
|
);
|
|
58
66
|
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "Ubuntu",
|
|
3
|
-
"image": "mcr.microsoft.com/devcontainers/base:noble",
|
|
4
|
-
"features": {
|
|
5
|
-
"ghcr.io/devcontainers/features/github-cli:1": {},
|
|
6
|
-
"ghcr.io/devcontainers/features/azure-cli:latest": {},
|
|
7
|
-
"ghcr.io/devcontainers/features/docker-outside-of-docker": {}
|
|
8
|
-
},
|
|
9
|
-
"postCreateCommand": "./.devcontainer/install-prerequisites.sh",
|
|
10
|
-
"customizations": {
|
|
11
|
-
"vscode": {
|
|
12
|
-
"extensions": [
|
|
13
|
-
"oven.bun-vscode",
|
|
14
|
-
"ms-azuretools.vscode-docker",
|
|
15
|
-
"SanjulaGanepola.github-local-actions"
|
|
16
|
-
]
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
}
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
|
|
3
|
-
set -e
|
|
4
|
-
|
|
5
|
-
# if bun is not installed, install it
|
|
6
|
-
if ! command -v bun &> /dev/null
|
|
7
|
-
then
|
|
8
|
-
echo "Bun not found, installing..."
|
|
9
|
-
|
|
10
|
-
curl -fsSL https://bun.com/install | bash
|
|
11
|
-
|
|
12
|
-
# manual fix for missing package.json issue
|
|
13
|
-
if [ ! -f "$HOME/.bun/install/global/package.json" ]; then
|
|
14
|
-
echo "Creating missing package.json for bun global..."
|
|
15
|
-
mkdir -p "$HOME/.bun/install/global"
|
|
16
|
-
echo '{}' > "$HOME/.bun/install/global/package.json"
|
|
17
|
-
fi
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
# add bun to PATH
|
|
21
|
-
export PATH="$HOME/.bun/bin:$PATH"
|
|
22
|
-
fi
|
|
23
|
-
|
|
24
|
-
# if there is no symlink for node, create it
|
|
25
|
-
if ! command -v node &> /dev/null
|
|
26
|
-
then
|
|
27
|
-
# discover the bun binary location
|
|
28
|
-
bunBinary=$(which bun)
|
|
29
|
-
echo "Bun binary located at: $bunBinary"
|
|
30
|
-
echo "Creating symlink for node to bun..."
|
|
31
|
-
mkdir -p $HOME/.local/bin
|
|
32
|
-
ln -sf "$bunBinary" "$HOME/.local/bin/node"
|
|
33
|
-
fi
|
|
34
|
-
|
|
35
|
-
export BUN_INSTALL_BIN=$HOME/.bun/bin
|
|
36
|
-
export BUN_INSTALL_GLOBAL_DIR=$HOME/.bun/global
|
|
37
|
-
|
|
38
|
-
# Ensure dirs exist and are owned by the current user
|
|
39
|
-
mkdir -p "$BUN_INSTALL_BIN" "$BUN_INSTALL_GLOBAL_DIR"
|
|
40
|
-
export PATH="$HOME/.bun/bin:$HOME/.bun/global/bin:${PATH}"
|
|
41
|
-
|
|
42
|
-
# add the paths to bashrc and zshrc
|
|
43
|
-
echo 'export PATH="$HOME/.bun/bin:$HOME/.bun/global/bin:${PATH}" ' >> $HOME/.bashrc
|
|
44
|
-
echo 'export PATH="$HOME/.bun/bin:$HOME/.bun/global/bin:${PATH}" '>> $HOME/.zshrc
|
|
45
|
-
|
|
46
|
-
# ensure $HOME/.local/bin is in PATH for current session and future shells
|
|
47
|
-
export PATH="$HOME/.local/bin:$PATH"
|
|
48
|
-
echo 'export PATH="$HOME/.local/bin:$PATH"' >> "$HOME/.bashrc"
|
|
49
|
-
echo 'export PATH="$HOME/.local/bin:$PATH"' >> "$HOME/.zshrc"
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
name: "Copilot Setup Steps"
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
workflow_dispatch:
|
|
5
|
-
push:
|
|
6
|
-
paths:
|
|
7
|
-
- .github/workflows/copilot-setup-steps.yml
|
|
8
|
-
pull_request:
|
|
9
|
-
paths:
|
|
10
|
-
- .github/workflows/copilot-setup-steps.yml
|
|
11
|
-
|
|
12
|
-
jobs:
|
|
13
|
-
# The job MUST be called `copilot-setup-steps` or it will not be picked up by Copilot.
|
|
14
|
-
copilot-setup-steps:
|
|
15
|
-
runs-on: ubuntu-latest
|
|
16
|
-
|
|
17
|
-
permissions:
|
|
18
|
-
contents: read
|
|
19
|
-
|
|
20
|
-
steps:
|
|
21
|
-
- name: Checkout repository
|
|
22
|
-
uses: actions/checkout@v6
|
|
23
|
-
|
|
24
|
-
- name: Install prerequisites
|
|
25
|
-
run: |
|
|
26
|
-
chmod +x ./.devcontainer/install-prerequisites.sh
|
|
27
|
-
./.devcontainer/install-prerequisites.sh
|
|
28
|
-
echo "$HOME/.bun/bin" >> $GITHUB_PATH
|
|
29
|
-
echo "$HOME/.bun/global/bin" >> $GITHUB_PATH
|
|
30
|
-
|
|
31
|
-
- name: Install dependencies
|
|
32
|
-
run: bun install
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
name: Pull Request
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
pull_request:
|
|
5
|
-
branches: [ "main" ]
|
|
6
|
-
|
|
7
|
-
jobs:
|
|
8
|
-
test:
|
|
9
|
-
runs-on: ubuntu-latest
|
|
10
|
-
environment: PR
|
|
11
|
-
|
|
12
|
-
steps:
|
|
13
|
-
- name: Checkout repository
|
|
14
|
-
uses: actions/checkout@v6
|
|
15
|
-
|
|
16
|
-
- name: Install prerequisites
|
|
17
|
-
run: |
|
|
18
|
-
chmod +x .devcontainer/install-prerequisites.sh
|
|
19
|
-
./.devcontainer/install-prerequisites.sh
|
|
20
|
-
echo "$HOME/.bun/bin" >> $GITHUB_PATH
|
|
21
|
-
echo "$HOME/.bun/global/bin" >> $GITHUB_PATH
|
|
22
|
-
|
|
23
|
-
- name: Install dependencies
|
|
24
|
-
run: bun install
|
|
25
|
-
|
|
26
|
-
- name: Run tests
|
|
27
|
-
run: bun test
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
name: Release NPM Package
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
release:
|
|
5
|
-
types: [published]
|
|
6
|
-
workflow_dispatch:
|
|
7
|
-
inputs:
|
|
8
|
-
tag:
|
|
9
|
-
description: 'Release tag (e.g., v1.2.3)'
|
|
10
|
-
required: true
|
|
11
|
-
|
|
12
|
-
jobs:
|
|
13
|
-
publish:
|
|
14
|
-
name: Publish Package
|
|
15
|
-
runs-on: ubuntu-latest
|
|
16
|
-
permissions:
|
|
17
|
-
contents: read
|
|
18
|
-
id-token: write
|
|
19
|
-
steps:
|
|
20
|
-
- name: Determine release tag
|
|
21
|
-
id: get_tag
|
|
22
|
-
run: |
|
|
23
|
-
echo "Event name: ${{ github.event_name }}"
|
|
24
|
-
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
|
25
|
-
TAG="${{ github.event.inputs.tag }}"
|
|
26
|
-
else
|
|
27
|
-
TAG="${{ github.event.release.tag_name }}"
|
|
28
|
-
fi
|
|
29
|
-
|
|
30
|
-
# if the tag is empty, exit with error
|
|
31
|
-
if [ -z "$TAG" ]; then
|
|
32
|
-
echo "Error: Tag is empty"
|
|
33
|
-
exit 1
|
|
34
|
-
fi
|
|
35
|
-
|
|
36
|
-
# Strip 'v' prefix if present
|
|
37
|
-
VERSION="${TAG#v}"
|
|
38
|
-
|
|
39
|
-
echo "Using tag: $TAG"
|
|
40
|
-
echo "Using version: $VERSION"
|
|
41
|
-
|
|
42
|
-
echo "tag=$TAG" >> $GITHUB_OUTPUT
|
|
43
|
-
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
|
44
|
-
|
|
45
|
-
- name: Checkout repository
|
|
46
|
-
uses: actions/checkout@v6
|
|
47
|
-
with:
|
|
48
|
-
ref: ${{ steps.get_tag.outputs.tag }}
|
|
49
|
-
|
|
50
|
-
- name: Install bun
|
|
51
|
-
run: |
|
|
52
|
-
curl -fsSL https://bun.com/install | bash
|
|
53
|
-
echo "$HOME/.bun/bin" >> $GITHUB_PATH
|
|
54
|
-
|
|
55
|
-
- uses: actions/setup-node@v4
|
|
56
|
-
with:
|
|
57
|
-
node-version: '24'
|
|
58
|
-
registry-url: 'https://registry.npmjs.org'
|
|
59
|
-
|
|
60
|
-
- name: Set package version
|
|
61
|
-
run: |
|
|
62
|
-
VERSION="${{ steps.get_tag.outputs.version }}"
|
|
63
|
-
jq --arg version "$VERSION" '.version = $version' package.json > package.json.tmp && mv package.json.tmp package.json
|
|
64
|
-
|
|
65
|
-
- name: Verify package version
|
|
66
|
-
run: |
|
|
67
|
-
EXPECTED_VERSION="${{ steps.get_tag.outputs.version }}"
|
|
68
|
-
ACTUAL_VERSION=$(jq -r '.version' package.json)
|
|
69
|
-
if [ "$EXPECTED_VERSION" != "$ACTUAL_VERSION" ]; then
|
|
70
|
-
echo "Error: Version mismatch. Expected $EXPECTED_VERSION, got $ACTUAL_VERSION"
|
|
71
|
-
exit 1
|
|
72
|
-
fi
|
|
73
|
-
echo "Version verified: $ACTUAL_VERSION"
|
|
74
|
-
|
|
75
|
-
- name: Install dependencies
|
|
76
|
-
run: bun install
|
|
77
|
-
- name: Build package
|
|
78
|
-
run: bun run build
|
|
79
|
-
|
|
80
|
-
- name: Publish Package
|
|
81
|
-
run: npm publish --no-build
|
package/AGENTS.md
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
## General guidelines
|
|
2
|
-
|
|
3
|
-
- Never use `git` operations. That's up to the user.
|
|
4
|
-
- Always prefer simplicity, usability and top level type safety over cleverness.
|
|
5
|
-
- Don't create index.ts files that re-export things from other files. Always import directly from the file you need.
|
|
6
|
-
- Prefer classes over standalone functions when it makes sense.
|
|
7
|
-
- Before doing something, check the patterns used in the rest of the codebase.
|
|
8
|
-
- Never use `import("...")` dynamic imports. Always use static imports (unless absolutely necessary).
|
|
9
|
-
|
|
10
|
-
## Bun specifics
|
|
11
|
-
This is a Bun-only project. Never check if something might not be supported in another environment. You can assume Bun is always available.
|
|
12
|
-
|
|
13
|
-
Always use Bun features and APIs where possible.
|
|
14
|
-
|
|
15
|
-
- Use `bun <file>` instead of `node <file>` or `ts-node <file>`
|
|
16
|
-
- Use `bun test` instead of `jest` or `vitest`
|
|
17
|
-
- Use `bun build <file.html|file.ts|file.css>` instead of `webpack` or `esbuild`
|
|
18
|
-
- Use `bun install` instead of `npm install` or `yarn install` or `pnpm install`
|
|
19
|
-
- Use `bun run <script>` instead of `npm run <script>` or `yarn run <script>` or `pnpm run <script>`
|
|
20
|
-
- Use `bunx <package> <command>` instead of `npx <package> <command>`
|
|
21
|
-
- Bun automatically loads .env, so don't use dotenv.
|
|
22
|
-
|
|
23
|
-
## APIs
|
|
24
|
-
|
|
25
|
-
- Prefer `Bun.file` over `node:fs`'s readFile/writeFile
|
|
26
|
-
- Bun.$`ls` instead of execa.
|
|
27
|
-
|
|
28
|
-
## Testing
|
|
29
|
-
|
|
30
|
-
Always run `bun run build` before running tests, to make sure there are no build errors.
|
|
31
|
-
Use `bun run test` to run all the tests.
|
|
32
|
-
|
|
33
|
-
Always run `bun run test` when you think you are done making changes.
|
|
34
|
-
|
|
35
|
-
```ts#index.test.ts
|
|
36
|
-
import { test, expect } from "bun:test";
|
|
37
|
-
|
|
38
|
-
test("hello world", () => {
|
|
39
|
-
expect(1).toBe(1);
|
|
40
|
-
});
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
For more information, read the Bun API docs in `node_modules/bun-types/docs/**.mdx`.
|
package/CLAUDE.md
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
@AGENTS.md
|