aRustyDev / aRustyDev/mdbook-htmx

docs(adr): ADR-0011: TypeScript for Reference Implementation Scripts

Open
#19 0 comments 0 reactions 1 assignee Claimed by @aRustyDev View on GitHub
documentation
Dominant language
Rust
Stars
0
Forks
1
PR merge metrics
No merged PRs in 30d

Description

# ADR-0011: TypeScript for Reference Implementation Scripts

## Status

Accepted

## Context

ADR-0010 establishes that mdbook-htmx generates server-side reference scripts. This ADR addresses the language choice: TypeScript vs JavaScript.

## Decision Drivers

1. **Self-Documentation** - Types describe manifest schema without separate docs
2. **Error Prevention** - Catch type mismatches at compile time
3. **IDE Support** - Autocomplete, refactoring, go-to-definition
4. **Runtime Compatibility** - Must work in Workers, Node, Deno, Bun
5. **User Accessibility** - Not all users know TypeScript

## Options Considered

### Option A: JavaScript Only

Plain JavaScript with JSDoc comments for types.

```javascript
/**
* @param {import('./types').User | null} user
* @param {import('./types').Page} page
* @returns {boolean}
*/
function isAuthorized(user, page) {
return page.auth.access === 'public' || user !== null;
}
```

**Pros:**
- No build step
- Universally understood
- Runs directly in Node

**Cons:**
- Types are comments, not enforced
- Verbose JSDoc for complex types
- Less IDE support than native TS

### Option B: TypeScript (Recommended)

TypeScript with explicit types.

```typescript
import type { User, Page } from './types';

function isAuthorized(user: User | null, page: Page): boolean {
return page.auth.access === 'public' || user !== null;
}
```

**Pros:**
- Types are enforced
- Self-documenting
- Excellent IDE support
- Catches errors before runtime
- Industry standard for server-side code

**Cons:**
- Requires build step
- Learning curve for some users

### Option C: Both (Generate TS, Transpile to JS)

Generate TypeScript, also include transpiled JavaScript.

```
book/htmx/scripts/
├── src/ # TypeScript source
│ └── *.ts
├── dist/ # Transpiled JavaScript
│ └── *.js
└── types/ # Declaration files
└── *.d.ts
```

**Pros:**
- TypeScript users get native TS
- JavaScript users get working code
- Type definitions available for both

**Cons:**
- Larger output
- Two versions to maintain conceptually

## Decision

**TypeScript as default, with JavaScript output option.**

Default configuration:
```toml
[output.htmx.scripts]
language = "typescript"
emit-js = false # Also emit transpiled JS
emit-declarations = true # Emit .d.ts files
```

Users can set `language = "javascript"` for plain JS output with JSDoc.

## Rationale

1. **Types Document the Manifest**

```typescript
// Types ARE the documentation
interface Page {
auth: {
access: 'public' | 'authenticated' | 'roles';
roles?: string[];
};
}
```

Users reading the code understand the manifest structure without separate docs.

2. **Cloudflare Workers Natively Supports TypeScript**

```bash
# wrangler handles TypeScript automatically
wrangler deploy
```

No separate build step for the primary deployment target.

3. **Error Prevention**

```typescript
// Caught at compile time
if (page.auth.access === 'admin') { // Error: 'admin' not in union type
```

4. **Modern Standard**

TypeScript is the de facto standard for:
- Cloudflare Workers
- Deno (native support)
- Node.js server applications
- Most modern web frameworks

## Bundle Size Considerations

TypeScript transpiles to JavaScript with **zero runtime overhead**:

| Metric | TypeScript | Transpiled JS |
|--------|------------|---------------|
| Bundle size | N/A (source) | Same as hand-written JS |
| Runtime perf | N/A | Identical |
| Types at runtime | Erased | None |

The `type` imports are completely removed:

```typescript
// Source
import type { Page } from './types';

// Transpiled - import disappears
```

## Configuration

```toml
[output.htmx.scripts]
enabled = true
language = "typescript" # typescript | javascript

# TypeScript options
target = "es2022" # ECMAScript target
module = "esm" # esm | commonjs
strict = true # Strict type checking
emit-js = false # Also generate .js files
emit-declarations = true # Generate .d.ts files
```

## Consequences

### Positive
- Types serve as schema documentation
- Compile-time error catching
- Better IDE experience
- Industry-standard choice
- Native Workers/Deno support

### Negative
- Some users unfamiliar with TypeScript
- Build step required for Node.js (unless using ts-node)

### Mitigation
- Include transpiled JS as option (`emit-js = true`)
- Provide tsconfig.json with recommended settings
- Document common TypeScript patterns

## References

- [TypeScript Handbook](https://www.typescriptlang.org/docs/handbook/)
- [Cloudflare Workers TypeScript](https://developers.cloudflare.com/workers/languages/typescript/)
- [Deno TypeScript Support](https://deno.land/manual/typescript)
- [Type-Only Imports](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html#type-only-imports-and-export)

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.