|
| 1 | +# Code Generation Tools |
| 2 | + |
| 3 | +This directory contains scripts for generating language-specific libraries from the TypeScript source definitions. |
| 4 | + |
| 5 | +## Overview |
| 6 | + |
| 7 | +The CabinCrew Protocol uses TypeScript as the **single source of truth** for all type definitions. These scripts generate: |
| 8 | + |
| 9 | +1. **JSON Schema** - Canonical schema for validation |
| 10 | +2. **Go Library** - Type-safe Go bindings |
| 11 | +3. **Python Library** - Pydantic v2 models |
| 12 | +4. **TypeScript/Node.js Library** - Type definitions for Node.js |
| 13 | + |
| 14 | +## Prerequisites |
| 15 | + |
| 16 | +### Node.js Dependencies |
| 17 | +```bash |
| 18 | +npm install |
| 19 | +``` |
| 20 | + |
| 21 | +### Python Generator (datamodel-code-generator) |
| 22 | +```bash |
| 23 | +# In a virtual environment (recommended) |
| 24 | +python3 -m venv venv |
| 25 | +source venv/bin/activate # On Windows: venv\Scripts\activate |
| 26 | +pip install -r requirements-dev.txt |
| 27 | +``` |
| 28 | + |
| 29 | +## Generation Scripts |
| 30 | + |
| 31 | +### `generate-schema.ts` |
| 32 | +Generates JSON Schema and MDX documentation from TypeScript source. |
| 33 | + |
| 34 | +**Tool**: `typescript-json-schema` |
| 35 | + |
| 36 | +**Output**: |
| 37 | +- `schemas/draft/schema.json` - JSON Schema Draft-07 |
| 38 | +- `schemas/draft/schema.mdx` - Human-readable documentation |
| 39 | + |
| 40 | +**Run**: `npm run generate` |
| 41 | + |
| 42 | +**Key Features**: |
| 43 | +- Extracts JSDoc comments as descriptions |
| 44 | +- Supports `@format`, `@type`, `@minimum`, `@maximum` annotations |
| 45 | +- Post-processes to fix `RecordStringAny` type |
| 46 | +- Removes duplicate `Record<string,any>` definitions |
| 47 | + |
| 48 | +### `generate-go.ts` |
| 49 | +Generates Go library from JSON Schema. |
| 50 | + |
| 51 | +**Tool**: `quicktype-core` |
| 52 | + |
| 53 | +**Output**: `lib/go/cabincrew/protocol.go` |
| 54 | + |
| 55 | +**Run**: `npm run generate:go` |
| 56 | + |
| 57 | +**Key Features**: |
| 58 | +- Generates Go structs with JSON tags |
| 59 | +- Post-processes to replace `RecordStringAny` with `map[string]interface{}` |
| 60 | +- Moves import statements to top of file |
| 61 | +- Validates no collision types (Purple, Fluffy, etc.) |
| 62 | + |
| 63 | +### `generate-python.ts` |
| 64 | +Generates Python Pydantic models from JSON Schema. |
| 65 | + |
| 66 | +**Tool**: `datamodel-code-generator` |
| 67 | + |
| 68 | +**Output**: `lib/python/src/cabincrew_protocol/protocol.py` |
| 69 | + |
| 70 | +**Run**: `npm run generate:python` |
| 71 | + |
| 72 | +**Key Features**: |
| 73 | +- Generates Pydantic v2 BaseModel classes |
| 74 | +- Proper required vs optional field handling |
| 75 | +- Field constraints (min, max, pattern) |
| 76 | +- Enum support |
| 77 | +- Timestamp removed post-generation to prevent CI desync |
| 78 | + |
| 79 | +**Why Pydantic over dataclasses?** |
| 80 | +- Better validation |
| 81 | +- Proper required field enforcement |
| 82 | +- JSON schema native support |
| 83 | +- No field ordering issues |
| 84 | + |
| 85 | +### `generate-nodejs.ts` |
| 86 | +Generates TypeScript library from JSON Schema. |
| 87 | + |
| 88 | +**Tool**: `quicktype-core` |
| 89 | + |
| 90 | +**Output**: `lib/nodejs/src/protocol.ts` |
| 91 | + |
| 92 | +**Run**: `npm run generate:nodejs` |
| 93 | + |
| 94 | +**Key Features**: |
| 95 | +- Generates TypeScript interfaces |
| 96 | +- Type aliases for enums |
| 97 | +- Validates no collision types |
| 98 | + |
| 99 | +## Important Annotations |
| 100 | + |
| 101 | +### `@type integer` |
| 102 | +Forces JSON Schema to use `"type": "integer"` instead of `"type": "number"`: |
| 103 | +```typescript |
| 104 | +/** |
| 105 | + * Monotonic sequence number. |
| 106 | + * @type integer |
| 107 | + * @minimum 0 |
| 108 | + */ |
| 109 | +sequence: number; |
| 110 | +``` |
| 111 | + |
| 112 | +### `@format date-time` |
| 113 | +Marks string fields as RFC3339 timestamps: |
| 114 | +```typescript |
| 115 | +/** @format date-time */ |
| 116 | +timestamp: string; |
| 117 | +``` |
| 118 | + |
| 119 | +### `@minimum` / `@maximum` |
| 120 | +Adds numeric constraints: |
| 121 | +```typescript |
| 122 | +/** |
| 123 | + * @minimum 0 |
| 124 | + * @maximum 3 |
| 125 | + */ |
| 126 | +severity: number; |
| 127 | +``` |
| 128 | + |
| 129 | +## Smoke Tests |
| 130 | + |
| 131 | +After generation, run smoke tests to verify libraries: |
| 132 | + |
| 133 | +```bash |
| 134 | +# Python |
| 135 | +python3 tests/smoke_test_python.py |
| 136 | + |
| 137 | +# TypeScript/Node.js |
| 138 | +npx ts-node tests/smoke_test_nodejs.ts |
| 139 | + |
| 140 | +# Go |
| 141 | +GO111MODULE=off go run tests/smoke_test_go.go |
| 142 | +``` |
| 143 | + |
| 144 | +## CI/CD |
| 145 | + |
| 146 | +The CI pipeline (`github/workflows/ci.yml`): |
| 147 | +1. Installs all dependencies |
| 148 | +2. Regenerates all libraries |
| 149 | +3. Checks for uncommitted changes (desync detection) |
| 150 | +4. Runs smoke tests |
| 151 | + |
| 152 | +If you modify TypeScript source, you **must** regenerate all libraries and commit the changes. |
| 153 | + |
| 154 | +## Troubleshooting |
| 155 | + |
| 156 | +### Python: "ModuleNotFoundError: No module named 'pydantic'" |
| 157 | +Install dependencies: `pip install -r requirements-dev.txt` |
| 158 | + |
| 159 | +### Go: "undefined: cabincrew" |
| 160 | +Run with `GO111MODULE=off` or from repository root |
| 161 | + |
| 162 | +### Timestamp causing CI desync |
| 163 | +The Python generator includes a timestamp comment. This is automatically removed by sed in the generation script and CI. |
| 164 | + |
| 165 | +### Collision types (Purple, Fluffy, etc.) |
| 166 | +These indicate quicktype found naming conflicts. Review the schema for duplicate type names. |
0 commit comments