bip-321 0.0.2 → 0.0.3
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/AGENTS.md +261 -0
- package/README.md +3 -21
- package/index.test.ts +0 -6
- package/index.ts +1 -14
- package/package.json +1 -1
- package/CLAUDE.md +0 -107
package/AGENTS.md
ADDED
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
# BIP-321 Parser - Agent Development Guide
|
|
2
|
+
|
|
3
|
+
This document provides guidance for AI agents and developers working on the BIP-321 Bitcoin URI parser library.
|
|
4
|
+
|
|
5
|
+
## Project Overview
|
|
6
|
+
|
|
7
|
+
A TypeScript/JavaScript library for parsing BIP-321 Bitcoin URIs with support for multiple payment methods (on-chain, Lightning, BOLT12, Silent Payments). Works natively in Node.js, browsers, and React Native without build tools.
|
|
8
|
+
|
|
9
|
+
## Tech Stack
|
|
10
|
+
|
|
11
|
+
### Runtime
|
|
12
|
+
- **Bun** - Primary development runtime
|
|
13
|
+
- Use `bun test` instead of `jest` or `vitest`
|
|
14
|
+
- Use `bun <file>` instead of `node <file>` or `ts-node <file>`
|
|
15
|
+
- Use `bun install` for package management
|
|
16
|
+
|
|
17
|
+
### Key Dependencies
|
|
18
|
+
|
|
19
|
+
**Why These Specific Dependencies:**
|
|
20
|
+
|
|
21
|
+
1. **`@scure/base`** (^2.0.0)
|
|
22
|
+
- Pure JavaScript base58, bech32, and bech32m encoding
|
|
23
|
+
- Works natively in all environments (Node.js, browser, React Native)
|
|
24
|
+
- No browserify or build tools needed
|
|
25
|
+
- Used for Base58 address decoding and bech32/bech32m validation
|
|
26
|
+
|
|
27
|
+
2. **`@noble/hashes`** (^2.0.1)
|
|
28
|
+
- Pure JavaScript cryptographic hashing (SHA-256)
|
|
29
|
+
- Properly exports all modules (no import warnings)
|
|
30
|
+
- Used for Base58Check checksum validation
|
|
31
|
+
- Import path: `@noble/hashes/sha2.js` (with .js extension)
|
|
32
|
+
|
|
33
|
+
3. **`bitcoinjs-lib`** (^7.0.0)
|
|
34
|
+
- Standard Bitcoin library for address validation
|
|
35
|
+
- Note: Taproot addresses require manual bech32m validation (ECC lib not initialized)
|
|
36
|
+
- Fallback to `@scure/base` for taproot validation
|
|
37
|
+
|
|
38
|
+
4. **`light-bolt11-decoder`** (^3.2.0)
|
|
39
|
+
- Lightweight Lightning BOLT11 invoice parser
|
|
40
|
+
- No heavy dependencies
|
|
41
|
+
|
|
42
|
+
### What We AVOID
|
|
43
|
+
|
|
44
|
+
- ❌ `bs58` - Requires browserify for browsers
|
|
45
|
+
- ❌ `bs58check` - Has module export warnings with `@noble/hashes`
|
|
46
|
+
- ❌ `express` or heavy server frameworks
|
|
47
|
+
- ❌ Build tools (webpack, browserify, rollup)
|
|
48
|
+
|
|
49
|
+
## Development Commands
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
# Run tests
|
|
53
|
+
bun test
|
|
54
|
+
|
|
55
|
+
# Run TypeScript type check
|
|
56
|
+
bun run check
|
|
57
|
+
# or
|
|
58
|
+
bunx tsc --noEmit
|
|
59
|
+
|
|
60
|
+
# Run examples
|
|
61
|
+
bun example.ts
|
|
62
|
+
|
|
63
|
+
# Run linter
|
|
64
|
+
bun run lint
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Project Structure
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
bip-321/
|
|
71
|
+
├── index.ts # Main parser implementation
|
|
72
|
+
├── index.test.ts # Comprehensive test suite (39 tests)
|
|
73
|
+
├── example.ts # Usage examples
|
|
74
|
+
├── README.md # User documentation
|
|
75
|
+
├── CLAUDE.md # Bun-specific development rules
|
|
76
|
+
├── AGENTS.md # This file
|
|
77
|
+
├── package.json # Dependencies and scripts
|
|
78
|
+
└── tsconfig.json # TypeScript configuration
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Key Design Decisions
|
|
82
|
+
|
|
83
|
+
### 1. Network Detection Strategy
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
// Order matters for Lightning invoices!
|
|
87
|
+
// Check "lnbcrt" before "lnbc" to avoid false positives
|
|
88
|
+
if (lowerInvoice.startsWith("lnbcrt")) return "regtest";
|
|
89
|
+
else if (lowerInvoice.startsWith("lnbc")) return "mainnet";
|
|
90
|
+
else if (lowerInvoice.startsWith("lntbs")) return "signet";
|
|
91
|
+
else if (lowerInvoice.startsWith("lntb")) return "testnet";
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### 2. Taproot Address Validation
|
|
95
|
+
|
|
96
|
+
bitcoinjs-lib requires ECC library initialization for taproot validation, so we use manual bech32m validation:
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
// Fallback to manual bech32/bech32m validation for taproot
|
|
100
|
+
const decoded = lowerAddress.startsWith("bc1p")
|
|
101
|
+
? bech32m.decode(address as `${string}1${string}`, 90)
|
|
102
|
+
: bech32.decode(address as `${string}1${string}`, 90);
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### 3. Base58Check Validation
|
|
106
|
+
|
|
107
|
+
Manual implementation using `@scure/base` + `@noble/hashes` to avoid dependencies with browser compatibility issues:
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
const decoded = base58.decode(address);
|
|
111
|
+
const payload = decoded.slice(0, -4);
|
|
112
|
+
const checksum = decoded.slice(-4);
|
|
113
|
+
const hash = sha256(sha256(payload)); // Double SHA-256
|
|
114
|
+
// Verify checksum matches
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### 4. Query Parameter Parsing
|
|
118
|
+
|
|
119
|
+
Manual parsing instead of `URLSearchParams` to preserve encoded values for `pop` parameter:
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
// Parse manually to preserve encoded values for pop parameter
|
|
123
|
+
const paramPairs = queryString.split("&");
|
|
124
|
+
// Keep pop value encoded as per BIP-321 spec
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Supported Payment Methods
|
|
128
|
+
|
|
129
|
+
| Type | Parameter | Validation | Notes |
|
|
130
|
+
|------|-----------|------------|-------|
|
|
131
|
+
| On-chain | `address`, `bc`, `tb`, `bcrt` | Full validation with network check | P2PKH, P2SH, Segwit, Taproot |
|
|
132
|
+
| Lightning | `lightning` | BOLT11 decode + network detection | Mainnet, testnet, regtest, signet |
|
|
133
|
+
| BOLT12 | `lno` | Accept any value | Offers (minimal validation) |
|
|
134
|
+
| Silent Payments | `sp` | Prefix check (`sp1`) | BIP-352 addresses |
|
|
135
|
+
|
|
136
|
+
**Removed:** BIP-351 Private Payments (`pay` parameter) - Unused spec, nobody knows what it is
|
|
137
|
+
|
|
138
|
+
## Testing Guidelines
|
|
139
|
+
|
|
140
|
+
### Test Structure
|
|
141
|
+
- 39 tests covering all functionality
|
|
142
|
+
- Use `test()` and `expect()` from `bun:test`
|
|
143
|
+
- Group related tests with `describe()`
|
|
144
|
+
- Use non-null assertions (`!`) where values are guaranteed to exist
|
|
145
|
+
|
|
146
|
+
### Example Test Pattern
|
|
147
|
+
```typescript
|
|
148
|
+
test("parses mainnet address", () => {
|
|
149
|
+
const result = parseBIP321("bitcoin:1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa");
|
|
150
|
+
expect(result.valid).toBe(true);
|
|
151
|
+
expect(result.network).toBe("mainnet");
|
|
152
|
+
expect(result.paymentMethods[0]!.type).toBe("onchain");
|
|
153
|
+
});
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## TypeScript Type Safety
|
|
157
|
+
|
|
158
|
+
All code must pass strict TypeScript checking with zero errors:
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
bunx tsc --noEmit # Must pass with 0 errors
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Common Type Patterns
|
|
165
|
+
|
|
166
|
+
```typescript
|
|
167
|
+
// Use non-null assertions for array access where guaranteed
|
|
168
|
+
result.paymentMethods[0]!.type
|
|
169
|
+
|
|
170
|
+
// Use optional chaining for potentially undefined values
|
|
171
|
+
result.paymentMethods[0]?.network
|
|
172
|
+
|
|
173
|
+
// Use nullish coalescing for fallbacks
|
|
174
|
+
byNetwork.mainnet?.length || 0
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## BIP-321 Compliance Rules
|
|
178
|
+
|
|
179
|
+
1. ✅ URI must start with `bitcoin:` (case-insensitive)
|
|
180
|
+
2. ✅ `label`, `message`, `amount`, `pop` cannot appear multiple times
|
|
181
|
+
3. ✅ `pop` and `req-pop` cannot both be present
|
|
182
|
+
4. ✅ Required parameters (`req-*`) must be understood or URI is invalid
|
|
183
|
+
5. ✅ Network-specific parameters must match address network
|
|
184
|
+
6. ✅ `pop` scheme must not be forbidden (http, https, file, javascript, mailto)
|
|
185
|
+
7. ✅ `amount` must be decimal BTC (no commas)
|
|
186
|
+
8. ✅ At least one valid payment method required
|
|
187
|
+
|
|
188
|
+
## Common Pitfalls
|
|
189
|
+
|
|
190
|
+
### ❌ Don't Do This
|
|
191
|
+
```typescript
|
|
192
|
+
// Wrong: Using .js imports breaks TypeScript
|
|
193
|
+
import { sha256 } from "@noble/hashes/sha2";
|
|
194
|
+
|
|
195
|
+
// Wrong: bs58 requires browserify
|
|
196
|
+
import bs58 from "bs58";
|
|
197
|
+
|
|
198
|
+
// Wrong: Checking lnbc before lnbcrt
|
|
199
|
+
if (invoice.startsWith("lnbc")) return "mainnet";
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### ✅ Do This
|
|
203
|
+
```typescript
|
|
204
|
+
// Correct: Use .js extension for @noble/hashes
|
|
205
|
+
import { sha256 } from "@noble/hashes/sha2.js";
|
|
206
|
+
|
|
207
|
+
// Correct: Use @scure/base (works everywhere)
|
|
208
|
+
import { base58 } from "@scure/base";
|
|
209
|
+
|
|
210
|
+
// Correct: Check longer prefix first
|
|
211
|
+
if (invoice.startsWith("lnbcrt")) return "regtest";
|
|
212
|
+
else if (invoice.startsWith("lnbc")) return "mainnet";
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
## Adding New Payment Methods
|
|
216
|
+
|
|
217
|
+
1. Add to `PaymentMethod` type union
|
|
218
|
+
2. Add parameter parsing in `parseBIP321()`
|
|
219
|
+
3. Implement validation function if needed
|
|
220
|
+
4. Add network detection if applicable
|
|
221
|
+
5. Write tests for new method
|
|
222
|
+
6. Update README documentation
|
|
223
|
+
7. Add example usage
|
|
224
|
+
|
|
225
|
+
## Browser Compatibility
|
|
226
|
+
|
|
227
|
+
All dependencies work natively in browsers via ES modules:
|
|
228
|
+
|
|
229
|
+
```html
|
|
230
|
+
<script type="module">
|
|
231
|
+
import { parseBIP321 } from './index.js';
|
|
232
|
+
// No build tools needed!
|
|
233
|
+
</script>
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
**No browserify, webpack, rollup, or any build tools required.**
|
|
237
|
+
|
|
238
|
+
## Performance Considerations
|
|
239
|
+
|
|
240
|
+
- Address validation is synchronous and fast
|
|
241
|
+
- Lightning invoice decoding is the slowest operation
|
|
242
|
+
- No async operations in the entire codebase
|
|
243
|
+
- Manual Base58 validation is faster than external libraries
|
|
244
|
+
|
|
245
|
+
## Contributing Guidelines
|
|
246
|
+
|
|
247
|
+
1. All changes must pass TypeScript type check (`bun run check`)
|
|
248
|
+
2. All tests must pass (`bun test`)
|
|
249
|
+
3. Add tests for new functionality
|
|
250
|
+
4. Update README for API changes
|
|
251
|
+
5. Keep dependencies minimal and browser-compatible
|
|
252
|
+
6. No build tools or polyfills
|
|
253
|
+
7. Maintain cross-platform compatibility (Node.js, browser, React Native)
|
|
254
|
+
|
|
255
|
+
## Resources
|
|
256
|
+
|
|
257
|
+
- [BIP-321 Specification](https://bips.dev/321/)
|
|
258
|
+
- [BIP-21 (Original)](https://github.com/bitcoin/bips/blob/master/bip-0021.mediawiki)
|
|
259
|
+
- [BIP-352 Silent Payments](https://github.com/bitcoin/bips/blob/master/bip-0352.mediawiki)
|
|
260
|
+
- [@scure/base Documentation](https://github.com/paulmillr/scure-base)
|
|
261
|
+
- [@noble/hashes Documentation](https://github.com/paulmillr/noble-hashes)
|
package/README.md
CHANGED
|
@@ -5,30 +5,23 @@ A TypeScript/JavaScript library for parsing BIP-321 Bitcoin URI scheme. This lib
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
7
|
- ✅ **Complete BIP-321 compliance** - Implements the full BIP-321 specification
|
|
8
|
-
- ✅ **Multiple payment methods** - Supports on-chain, Lightning (BOLT11), BOLT12 offers,
|
|
8
|
+
- ✅ **Multiple payment methods** - Supports on-chain, Lightning (BOLT11), BOLT12 offers, and silent payments
|
|
9
9
|
- ✅ **Network detection** - Automatically detects mainnet, testnet, regtest, and signet networks
|
|
10
10
|
- ✅ **Address validation** - Validates Bitcoin addresses (P2PKH, P2SH, Segwit v0, Taproot)
|
|
11
11
|
- ✅ **Lightning invoice validation** - Validates BOLT11 Lightning invoices
|
|
12
|
-
- ✅ **Cross-platform** - Works in Node.js, browsers, and React Native
|
|
13
|
-
- ✅ **TypeScript support** - Fully typed with TypeScript definitions
|
|
14
|
-
- ✅ **Proof of payment** - Supports pop/req-pop parameters for payment callbacks
|
|
15
|
-
- ✅ **Comprehensive error handling** - Clear error messages for invalid URIs
|
|
16
12
|
|
|
17
13
|
```typescript
|
|
18
14
|
import { parseBIP321, type BIP321ParseResult, type PaymentMethod } from "bip-321";
|
|
19
15
|
|
|
20
|
-
// Fully typed result with autocomplete support
|
|
21
16
|
const result: BIP321ParseResult = parseBIP321("bitcoin:...");
|
|
22
17
|
|
|
23
|
-
// TypeScript knows all available properties
|
|
24
18
|
result.valid; // boolean
|
|
25
19
|
result.network; // "mainnet" | "testnet" | "regtest" | "signet" | undefined
|
|
26
20
|
result.paymentMethods; // PaymentMethod[]
|
|
27
21
|
result.errors; // string[]
|
|
28
22
|
|
|
29
|
-
// Payment methods are also fully typed
|
|
30
23
|
result.paymentMethods.forEach((method: PaymentMethod) => {
|
|
31
|
-
method.type; // "onchain" | "lightning" | "lno" | "silent-payment" | "
|
|
24
|
+
method.type; // "onchain" | "lightning" | "lno" | "silent-payment" | "other"
|
|
32
25
|
method.network; // "mainnet" | "testnet" | "regtest" | "signet" | undefined
|
|
33
26
|
method.valid; // boolean
|
|
34
27
|
});
|
|
@@ -46,16 +39,6 @@ Or with npm:
|
|
|
46
39
|
npm install bip-321
|
|
47
40
|
```
|
|
48
41
|
|
|
49
|
-
### Note on Dependencies
|
|
50
|
-
|
|
51
|
-
This library uses modern, browser-native dependencies:
|
|
52
|
-
- **`@scure/base`** - Pure JavaScript base58, bech32, and bech32m encoding (no browserify needed)
|
|
53
|
-
- **`@noble/hashes`** - Pure JavaScript cryptographic hashing
|
|
54
|
-
- **`bitcoinjs-lib`** - Bitcoin address validation
|
|
55
|
-
- **`light-bolt11-decoder`** - Lightning invoice parsing
|
|
56
|
-
|
|
57
|
-
All dependencies work natively in Node.js, browsers, and React Native without any build tools or polyfills required.
|
|
58
|
-
|
|
59
42
|
## Quick Start
|
|
60
43
|
|
|
61
44
|
```typescript
|
|
@@ -198,7 +181,7 @@ interface BIP321ParseResult {
|
|
|
198
181
|
|
|
199
182
|
```typescript
|
|
200
183
|
interface PaymentMethod {
|
|
201
|
-
type: "onchain" | "lightning" | "lno" | "silent-payment" | "
|
|
184
|
+
type: "onchain" | "lightning" | "lno" | "silent-payment" | "other";
|
|
202
185
|
value: string; // The actual address/invoice value
|
|
203
186
|
network?: "mainnet" | "testnet" | "regtest" | "signet";
|
|
204
187
|
valid: boolean; // Whether this payment method is valid
|
|
@@ -250,7 +233,6 @@ console.log(summary);
|
|
|
250
233
|
| Lightning | `lightning` | BOLT11 Lightning invoices |
|
|
251
234
|
| BOLT12 | `lno` | Lightning BOLT12 offers |
|
|
252
235
|
| Silent Payments | `sp` | BIP352 Silent Payment addresses |
|
|
253
|
-
| Private Payments | `pay` | BIP351 Private Payment addresses |
|
|
254
236
|
|
|
255
237
|
## Network Detection
|
|
256
238
|
|
package/index.test.ts
CHANGED
|
@@ -186,12 +186,6 @@ describe("BIP-321 Parser", () => {
|
|
|
186
186
|
expect(result.valid).toBe(true);
|
|
187
187
|
expect(result.paymentMethods.length).toBe(2);
|
|
188
188
|
});
|
|
189
|
-
|
|
190
|
-
test("parses private payment address", () => {
|
|
191
|
-
const result = parseBIP321("bitcoin:?pay=bip351address");
|
|
192
|
-
expect(result.valid).toBe(true);
|
|
193
|
-
expect(result.paymentMethods[0]!.type).toBe("private-payment");
|
|
194
|
-
});
|
|
195
189
|
});
|
|
196
190
|
|
|
197
191
|
describe("Network-specific Parameters", () => {
|
package/index.ts
CHANGED
|
@@ -4,13 +4,7 @@ import { sha256 } from "@noble/hashes/sha2.js";
|
|
|
4
4
|
import { base58, bech32, bech32m } from "@scure/base";
|
|
5
5
|
|
|
6
6
|
export interface PaymentMethod {
|
|
7
|
-
type:
|
|
8
|
-
| "onchain"
|
|
9
|
-
| "lightning"
|
|
10
|
-
| "lno"
|
|
11
|
-
| "silent-payment"
|
|
12
|
-
| "private-payment"
|
|
13
|
-
| "other";
|
|
7
|
+
type: "onchain" | "lightning" | "lno" | "silent-payment" | "other";
|
|
14
8
|
value: string;
|
|
15
9
|
network?: "mainnet" | "testnet" | "regtest" | "signet";
|
|
16
10
|
valid: boolean;
|
|
@@ -353,13 +347,6 @@ export function parseBIP321(uri: string): BIP321ParseResult {
|
|
|
353
347
|
if (!isSilentPayment) {
|
|
354
348
|
result.errors.push("Invalid silent payment address format");
|
|
355
349
|
}
|
|
356
|
-
} else if (lowerKey === "pay") {
|
|
357
|
-
const decodedValue = decodeURIComponent(value);
|
|
358
|
-
result.paymentMethods.push({
|
|
359
|
-
type: "private-payment",
|
|
360
|
-
value: decodedValue,
|
|
361
|
-
valid: true,
|
|
362
|
-
});
|
|
363
350
|
} else if (
|
|
364
351
|
lowerKey === "bc" ||
|
|
365
352
|
lowerKey === "tb" ||
|
package/package.json
CHANGED
package/CLAUDE.md
DELETED
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
|
|
3
|
-
Default to using Bun instead of Node.js.
|
|
4
|
-
|
|
5
|
-
- Use `bun <file>` instead of `node <file>` or `ts-node <file>`
|
|
6
|
-
- Use `bun test` instead of `jest` or `vitest`
|
|
7
|
-
- Use `bun build <file.html|file.ts|file.css>` instead of `webpack` or `esbuild`
|
|
8
|
-
- Use `bun install` instead of `npm install` or `yarn install` or `pnpm install`
|
|
9
|
-
- Use `bun run <script>` instead of `npm run <script>` or `yarn run <script>` or `pnpm run <script>`
|
|
10
|
-
- Bun automatically loads .env, so don't use dotenv.
|
|
11
|
-
|
|
12
|
-
## APIs
|
|
13
|
-
|
|
14
|
-
- `Bun.serve()` supports WebSockets, HTTPS, and routes. Don't use `express`.
|
|
15
|
-
- `bun:sqlite` for SQLite. Don't use `better-sqlite3`.
|
|
16
|
-
- `Bun.redis` for Redis. Don't use `ioredis`.
|
|
17
|
-
- `Bun.sql` for Postgres. Don't use `pg` or `postgres.js`.
|
|
18
|
-
- `WebSocket` is built-in. Don't use `ws`.
|
|
19
|
-
- Prefer `Bun.file` over `node:fs`'s readFile/writeFile
|
|
20
|
-
- Bun.$`ls` instead of execa.
|
|
21
|
-
|
|
22
|
-
## Testing
|
|
23
|
-
|
|
24
|
-
Use `bun test` to run tests.
|
|
25
|
-
|
|
26
|
-
```ts#index.test.ts
|
|
27
|
-
import { test, expect } from "bun:test";
|
|
28
|
-
|
|
29
|
-
test("hello world", () => {
|
|
30
|
-
expect(1).toBe(1);
|
|
31
|
-
});
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
## Frontend
|
|
35
|
-
|
|
36
|
-
Use HTML imports with `Bun.serve()`. Don't use `vite`. HTML imports fully support React, CSS, Tailwind.
|
|
37
|
-
|
|
38
|
-
Server:
|
|
39
|
-
|
|
40
|
-
```ts#index.ts
|
|
41
|
-
import index from "./index.html"
|
|
42
|
-
|
|
43
|
-
Bun.serve({
|
|
44
|
-
routes: {
|
|
45
|
-
"/": index,
|
|
46
|
-
"/api/users/:id": {
|
|
47
|
-
GET: (req) => {
|
|
48
|
-
return new Response(JSON.stringify({ id: req.params.id }));
|
|
49
|
-
},
|
|
50
|
-
},
|
|
51
|
-
},
|
|
52
|
-
// optional websocket support
|
|
53
|
-
websocket: {
|
|
54
|
-
open: (ws) => {
|
|
55
|
-
ws.send("Hello, world!");
|
|
56
|
-
},
|
|
57
|
-
message: (ws, message) => {
|
|
58
|
-
ws.send(message);
|
|
59
|
-
},
|
|
60
|
-
close: (ws) => {
|
|
61
|
-
// handle close
|
|
62
|
-
}
|
|
63
|
-
},
|
|
64
|
-
development: {
|
|
65
|
-
hmr: true,
|
|
66
|
-
console: true,
|
|
67
|
-
}
|
|
68
|
-
})
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
HTML files can import .tsx, .jsx or .js files directly and Bun's bundler will transpile & bundle automatically. `<link>` tags can point to stylesheets and Bun's CSS bundler will bundle.
|
|
72
|
-
|
|
73
|
-
```html#index.html
|
|
74
|
-
<html>
|
|
75
|
-
<body>
|
|
76
|
-
<h1>Hello, world!</h1>
|
|
77
|
-
<script type="module" src="./frontend.tsx"></script>
|
|
78
|
-
</body>
|
|
79
|
-
</html>
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
With the following `frontend.tsx`:
|
|
83
|
-
|
|
84
|
-
```tsx#frontend.tsx
|
|
85
|
-
import React from "react";
|
|
86
|
-
|
|
87
|
-
// import .css files directly and it works
|
|
88
|
-
import './index.css';
|
|
89
|
-
|
|
90
|
-
import { createRoot } from "react-dom/client";
|
|
91
|
-
|
|
92
|
-
const root = createRoot(document.body);
|
|
93
|
-
|
|
94
|
-
export default function Frontend() {
|
|
95
|
-
return <h1>Hello, world!</h1>;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
root.render(<Frontend />);
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
Then, run index.ts
|
|
102
|
-
|
|
103
|
-
```sh
|
|
104
|
-
bun --hot ./index.ts
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
For more information, read the Bun API docs in `node_modules/bun-types/docs/**.md`.
|