@pablozaiden/terminatui 0.3.0-beta-1 → 0.4.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 (142) hide show
  1. package/package.json +10 -3
  2. package/src/__tests__/adapterNoSharedUi.test.ts +34 -0
  3. package/src/__tests__/configOnChange.test.ts +63 -0
  4. package/src/__tests__/schemaToFields.test.ts +0 -4
  5. package/src/__tests__/tuiRootNoCoupling.test.ts +25 -0
  6. package/src/builtins/version.ts +1 -1
  7. package/src/index.ts +22 -0
  8. package/src/tui/TuiApplication.tsx +0 -4
  9. package/src/tui/TuiRoot.tsx +58 -102
  10. package/src/tui/actions.ts +4 -0
  11. package/src/tui/adapters/ink/InkRenderer.tsx +191 -41
  12. package/src/tui/adapters/ink/SemanticInkRenderer.tsx +210 -0
  13. package/src/tui/adapters/ink/components/Button.tsx +10 -2
  14. package/src/tui/adapters/ink/components/Overlay.tsx +8 -2
  15. package/src/tui/adapters/ink/components/Panel.tsx +26 -5
  16. package/src/tui/adapters/ink/components/ScrollView.tsx +44 -3
  17. package/src/tui/adapters/ink/components/Spinner.tsx +8 -2
  18. package/src/tui/adapters/ink/keyboard.ts +0 -3
  19. package/src/tui/adapters/ink/ui/CommandSelector.tsx +56 -0
  20. package/src/tui/adapters/ink/ui/ConfigForm.tsx +77 -0
  21. package/src/tui/adapters/ink/ui/Header.tsx +25 -0
  22. package/src/tui/adapters/ink/ui/JsonHighlight.tsx +21 -0
  23. package/src/tui/adapters/ink/ui/ResultsPanel.tsx +57 -0
  24. package/src/tui/adapters/opentui/OpenTuiRenderer.tsx +190 -39
  25. package/src/tui/adapters/opentui/SemanticOpenTuiRenderer.tsx +192 -0
  26. package/src/tui/adapters/opentui/components/Label.tsx +2 -2
  27. package/src/tui/adapters/opentui/components/Overlay.tsx +12 -3
  28. package/src/tui/adapters/opentui/components/Panel.tsx +11 -1
  29. package/src/tui/adapters/opentui/components/ScrollView.tsx +1 -8
  30. package/src/tui/adapters/opentui/components/Spinner.tsx +1 -1
  31. package/src/tui/adapters/opentui/keyboard.ts +0 -3
  32. package/src/tui/adapters/opentui/ui/CommandSelector.tsx +55 -0
  33. package/src/tui/adapters/opentui/ui/ConfigForm.tsx +74 -0
  34. package/src/tui/adapters/opentui/ui/Header.tsx +24 -0
  35. package/src/tui/adapters/opentui/ui/JsonHighlight.tsx +20 -0
  36. package/src/tui/adapters/opentui/ui/LogsPanel.tsx +44 -0
  37. package/src/tui/adapters/opentui/ui/ResultsPanel.tsx +62 -0
  38. package/src/tui/adapters/shared/TerminalClipboard.ts +65 -0
  39. package/src/tui/adapters/{opentui/hooks → shared}/useSpinner.ts +5 -1
  40. package/src/tui/adapters/types.ts +25 -45
  41. package/src/tui/components/JsonHighlight.tsx +41 -111
  42. package/src/tui/context/ActionContext.tsx +51 -0
  43. package/src/tui/context/ExecutorContext.tsx +7 -1
  44. package/src/tui/context/NavigationContext.tsx +20 -4
  45. package/src/tui/controllers/CommandBrowserController.tsx +100 -0
  46. package/src/tui/controllers/ConfigController.tsx +183 -0
  47. package/src/tui/controllers/EditorController.tsx +169 -0
  48. package/src/tui/controllers/LogsController.tsx +48 -0
  49. package/src/tui/controllers/OutcomeController.tsx +110 -0
  50. package/src/tui/driver/TuiDriver.tsx +148 -0
  51. package/src/tui/driver/context/TuiDriverContext.tsx +44 -0
  52. package/src/tui/driver/types.ts +72 -0
  53. package/src/tui/semantic/AppShell.tsx +30 -0
  54. package/src/tui/semantic/CommandBrowserScreen.tsx +16 -0
  55. package/src/tui/semantic/ConfigScreen.tsx +23 -0
  56. package/src/tui/semantic/EditorScreen.tsx +20 -0
  57. package/src/tui/semantic/LogsScreen.tsx +9 -0
  58. package/src/tui/semantic/RunningScreen.tsx +17 -0
  59. package/src/tui/semantic/layoutTypes.ts +72 -0
  60. package/src/tui/semantic/render.tsx +44 -0
  61. package/src/tui/semantic/types.ts +31 -98
  62. package/src/tui/utils/jsonTokenizer.ts +98 -0
  63. package/src/tui/utils/schemaToFields.ts +1 -25
  64. package/.devcontainer/devcontainer.json +0 -19
  65. package/.devcontainer/install-prerequisites.sh +0 -49
  66. package/.github/workflows/copilot-setup-steps.yml +0 -32
  67. package/.github/workflows/pull-request.yml +0 -27
  68. package/.github/workflows/release-npm-package.yml +0 -81
  69. package/AGENTS.md +0 -43
  70. package/CLAUDE.md +0 -1
  71. package/bun.lock +0 -321
  72. package/examples/tui-app/commands/config/app/get.ts +0 -62
  73. package/examples/tui-app/commands/config/app/index.ts +0 -23
  74. package/examples/tui-app/commands/config/app/set.ts +0 -96
  75. package/examples/tui-app/commands/config/index.ts +0 -28
  76. package/examples/tui-app/commands/config/user/get.ts +0 -61
  77. package/examples/tui-app/commands/config/user/index.ts +0 -23
  78. package/examples/tui-app/commands/config/user/set.ts +0 -57
  79. package/examples/tui-app/commands/greet.ts +0 -78
  80. package/examples/tui-app/commands/math.ts +0 -111
  81. package/examples/tui-app/commands/status.ts +0 -86
  82. package/examples/tui-app/index.ts +0 -38
  83. package/guides/01-hello-world.md +0 -101
  84. package/guides/02-adding-options.md +0 -103
  85. package/guides/03-multiple-commands.md +0 -161
  86. package/guides/04-subcommands.md +0 -206
  87. package/guides/05-interactive-tui.md +0 -209
  88. package/guides/06-config-validation.md +0 -256
  89. package/guides/07-async-cancellation.md +0 -334
  90. package/guides/08-complete-application.md +0 -507
  91. package/guides/README.md +0 -78
  92. package/src/tui/adapters/ink/components/Code.tsx +0 -6
  93. package/src/tui/adapters/ink/components/Container.tsx +0 -5
  94. package/src/tui/adapters/ink/components/Spacer.tsx +0 -15
  95. package/src/tui/adapters/ink/components/Value.tsx +0 -7
  96. package/src/tui/adapters/opentui/components/Code.tsx +0 -12
  97. package/src/tui/adapters/opentui/components/Container.tsx +0 -56
  98. package/src/tui/adapters/opentui/components/Spacer.tsx +0 -5
  99. package/src/tui/adapters/opentui/components/Value.tsx +0 -13
  100. package/src/tui/components/ActionButton.tsx +0 -0
  101. package/src/tui/components/CommandSelector.tsx +0 -119
  102. package/src/tui/components/ConfigForm.tsx +0 -174
  103. package/src/tui/components/FieldRow.tsx +0 -0
  104. package/src/tui/components/Header.tsx +0 -32
  105. package/src/tui/components/ModalBase.tsx +0 -38
  106. package/src/tui/components/ResultsPanel.tsx +0 -84
  107. package/src/tui/components/StatusBar.tsx +0 -44
  108. package/src/tui/components/logColors.ts +0 -12
  109. package/src/tui/components/types.ts +0 -30
  110. package/src/tui/context/ClipboardContext.tsx +0 -87
  111. package/src/tui/context/KeyboardContext.tsx +0 -132
  112. package/src/tui/hooks/useActiveKeyHandler.ts +0 -75
  113. package/src/tui/hooks/useClipboard.ts +0 -81
  114. package/src/tui/hooks/useClipboardProvider.ts +0 -42
  115. package/src/tui/hooks/useGlobalKeyHandler.ts +0 -54
  116. package/src/tui/modals/CliModal.tsx +0 -82
  117. package/src/tui/modals/EditorModal.tsx +0 -207
  118. package/src/tui/modals/LogsModal.tsx +0 -98
  119. package/src/tui/registry.ts +0 -102
  120. package/src/tui/screens/CommandSelectScreen.tsx +0 -162
  121. package/src/tui/screens/ConfigScreen.tsx +0 -160
  122. package/src/tui/screens/ErrorScreen.tsx +0 -58
  123. package/src/tui/screens/ResultsScreen.tsx +0 -60
  124. package/src/tui/screens/RunningScreen.tsx +0 -72
  125. package/src/tui/screens/ScreenBase.ts +0 -6
  126. package/src/tui/semantic/Button.tsx +0 -7
  127. package/src/tui/semantic/Code.tsx +0 -7
  128. package/src/tui/semantic/CodeHighlight.tsx +0 -7
  129. package/src/tui/semantic/Container.tsx +0 -7
  130. package/src/tui/semantic/Field.tsx +0 -7
  131. package/src/tui/semantic/Label.tsx +0 -7
  132. package/src/tui/semantic/MenuButton.tsx +0 -7
  133. package/src/tui/semantic/MenuItem.tsx +0 -7
  134. package/src/tui/semantic/Overlay.tsx +0 -7
  135. package/src/tui/semantic/Panel.tsx +0 -7
  136. package/src/tui/semantic/ScrollView.tsx +0 -9
  137. package/src/tui/semantic/Select.tsx +0 -7
  138. package/src/tui/semantic/Spacer.tsx +0 -7
  139. package/src/tui/semantic/Spinner.tsx +0 -7
  140. package/src/tui/semantic/TextInput.tsx +0 -7
  141. package/src/tui/semantic/Value.tsx +0 -7
  142. package/tsconfig.json +0 -25
@@ -0,0 +1,98 @@
1
+ import type { CodeTokenType } from "../semantic/types.ts";
2
+
3
+ /**
4
+ * A single token in a JSON line.
5
+ */
6
+ export type JsonToken = { type: Exclude<CodeTokenType, "unknown">; value: string };
7
+
8
+ /**
9
+ * A line of JSON tokens.
10
+ */
11
+ export type JsonLineTokens = JsonToken[];
12
+
13
+ /**
14
+ * Tokenize a JavaScript value into lines of syntax-highlighted JSON tokens.
15
+ *
16
+ * This is a pure behavioral helper with no React dependencies.
17
+ * Adapters can use this to build their own rendering.
18
+ */
19
+ export function tokenizeJsonValue(value: unknown, indent = 0): JsonLineTokens[] {
20
+ const pad = " ".repeat(indent);
21
+ const padToken = (): JsonToken => ({ type: "punctuation", value: pad });
22
+
23
+ if (value === null) {
24
+ return [[padToken(), { type: "null", value: "null" }]];
25
+ }
26
+ if (typeof value === "boolean") {
27
+ return [[padToken(), { type: "boolean", value: String(value) }]];
28
+ }
29
+ if (typeof value === "number") {
30
+ return [[padToken(), { type: "number", value: String(value) }]];
31
+ }
32
+ if (typeof value === "string") {
33
+ return [[padToken(), { type: "string", value: JSON.stringify(value) }]];
34
+ }
35
+ if (Array.isArray(value)) {
36
+ if (value.length === 0) {
37
+ return [[padToken(), { type: "punctuation", value: "[]" }]];
38
+ }
39
+ const lines: JsonLineTokens[] = [[padToken(), { type: "punctuation", value: "[" }]];
40
+ value.forEach((item, idx) => {
41
+ const itemLines = tokenizeJsonValue(item, indent + 1);
42
+ const isLast = idx === value.length - 1;
43
+ itemLines.forEach((line, lineIdx) => {
44
+ if (lineIdx === itemLines.length - 1 && !isLast) {
45
+ lines.push([...line, { type: "punctuation", value: "," }]);
46
+ } else {
47
+ lines.push(line);
48
+ }
49
+ });
50
+ });
51
+ lines.push([padToken(), { type: "punctuation", value: "]" }]);
52
+ return lines;
53
+ }
54
+ if (typeof value === "object") {
55
+ const entries = Object.entries(value);
56
+ if (entries.length === 0) {
57
+ return [[padToken(), { type: "punctuation", value: "{}" }]];
58
+ }
59
+ const lines: JsonLineTokens[] = [[padToken(), { type: "punctuation", value: "{" }]];
60
+ const innerPad = " ".repeat(indent + 1);
61
+
62
+ entries.forEach(([key, val], idx) => {
63
+ const valLines = tokenizeJsonValue(val, indent + 1);
64
+ const isLast = idx === entries.length - 1;
65
+
66
+ // First value line - prepend key
67
+ const firstValLine = valLines[0] ?? [];
68
+ // Remove the padding from value's first line (we'll add our own with the key)
69
+ const valTokens = firstValLine.filter((t) => t.value !== " ".repeat(indent + 1));
70
+
71
+ const keyLine: JsonLineTokens = [
72
+ { type: "punctuation", value: innerPad },
73
+ { type: "key", value: `"${key}"` },
74
+ { type: "punctuation", value: ": " },
75
+ ...valTokens,
76
+ ];
77
+
78
+ if (valLines.length === 1) {
79
+ // Single line value
80
+ if (!isLast) keyLine.push({ type: "punctuation", value: "," });
81
+ lines.push(keyLine);
82
+ } else {
83
+ // Multi-line value
84
+ lines.push(keyLine);
85
+ valLines.slice(1, -1).forEach((line) => lines.push(line));
86
+ const lastLine = valLines[valLines.length - 1] ?? [];
87
+ if (!isLast) {
88
+ lines.push([...lastLine, { type: "punctuation", value: "," }]);
89
+ } else {
90
+ lines.push(lastLine);
91
+ }
92
+ }
93
+ });
94
+ lines.push([padToken(), { type: "punctuation", value: "}" }]);
95
+ return lines;
96
+ }
97
+ return [];
98
+ }
@@ -1,5 +1,5 @@
1
1
  import type { OptionSchema, OptionDef } from "../../types/command.ts";
2
- import type { FieldConfig, FieldType, FieldOption } from "../components/types.ts";
2
+ import type { FieldConfig, FieldType, FieldOption } from "../semantic/types.ts";
3
3
 
4
4
  /**
5
5
  * Convert an option type to a field type.
@@ -75,8 +75,6 @@ export function schemaToFieldConfigs(schema: OptionSchema): FieldConfig[] {
75
75
  label: def.label ?? keyToLabel(key),
76
76
  type: optionTypeToFieldType(def),
77
77
  options: createFieldOptions(def),
78
- placeholder: def.placeholder,
79
- group: def.group,
80
78
  };
81
79
 
82
80
  fields.push(fieldConfig);
@@ -92,28 +90,6 @@ export function schemaToFieldConfigs(schema: OptionSchema): FieldConfig[] {
92
90
  return fields;
93
91
  }
94
92
 
95
- /**
96
- * Group field configs by their group property.
97
- *
98
- * @param fields - Field configs to group
99
- * @returns Map of group name to field configs
100
- */
101
- export function groupFieldConfigs(
102
- fields: FieldConfig[]
103
- ): Map<string | undefined, FieldConfig[]> {
104
- const groups = new Map<string | undefined, FieldConfig[]>();
105
-
106
- for (const field of fields) {
107
- const group = field.group;
108
- if (!groups.has(group)) {
109
- groups.set(group, []);
110
- }
111
- groups.get(group)!.push(field);
112
- }
113
-
114
- return groups;
115
- }
116
-
117
93
  /**
118
94
  * Get display value for a field.
119
95
  *
@@ -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