Skip to content

Commit 764cda2

Browse files
author
Prashant Patel
committed
Adding Typescript support
1 parent 00fbcdb commit 764cda2

29 files changed

+1637
-1
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33
*.swp
44
*.swo
55
*.swn
6+
*.cursorrules
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
# TypeScript Code Generation Project
2+
3+
This directory contains a TypeScript project that demonstrates code generation using `ion-cli` with TypeScript as the target language.
4+
5+
## Project Structure
6+
7+
```
8+
typescript/
9+
├── src/
10+
│ ├── models/ # Generated TypeScript interfaces
11+
│ ├── serializers/ # Ion serialization code
12+
│ └── validators/ # Schema validation code
13+
├── tests/
14+
│ ├── good/ # Valid test cases
15+
│ └── bad/ # Invalid test cases
16+
├── package.json
17+
└── tsconfig.json
18+
```
19+
20+
## Build Process
21+
22+
The TypeScript code generation is integrated into the build process using npm scripts. The build process:
23+
24+
1. Checks for `ion-cli` availability
25+
2. Generates TypeScript code from schemas
26+
3. Compiles TypeScript to JavaScript
27+
4. Runs tests
28+
29+
### NPM Scripts
30+
31+
```json
32+
{
33+
"scripts": {
34+
"generate": "ion-cli generate -l typescript -d ../../schema -o ./src/models",
35+
"build": "tsc",
36+
"test": "jest",
37+
"clean": "rm -rf ./src/models/*"
38+
}
39+
}
40+
```
41+
42+
### Environment Setup
43+
44+
1. Install ion-cli:
45+
```bash
46+
brew install ion-cli
47+
# or
48+
cargo install ion-cli
49+
```
50+
51+
2. Set up environment:
52+
```bash
53+
export ION_CLI=/path/to/ion-cli # Optional, defaults to 'ion'
54+
```
55+
56+
## Testing
57+
58+
The project includes comprehensive tests for the generated code:
59+
60+
### Unit Tests
61+
- Type guard validation
62+
- Serialization/deserialization
63+
- Null value handling
64+
- Type annotation preservation
65+
66+
### Integration Tests
67+
- Roundtrip testing with good/bad inputs
68+
- Schema validation
69+
- Error handling
70+
71+
### Running Tests
72+
73+
```bash
74+
npm test
75+
```
76+
77+
## Type System
78+
79+
The generated TypeScript code follows these principles:
80+
81+
1. **Null Safety**
82+
- Explicit null handling
83+
- Optional type support
84+
- Undefined vs null distinction
85+
86+
2. **Type Guards**
87+
- Runtime type checking
88+
- Custom validation rules
89+
- Schema constraint validation
90+
91+
3. **Serialization**
92+
- Binary format support
93+
- Text format support
94+
- Type annotation preservation
95+
96+
## Ion Type Mappings
97+
98+
| Ion Type | TypeScript Type |
99+
|----------|----------------|
100+
| null | null |
101+
| bool | boolean |
102+
| int | number/bigint |
103+
| float | number |
104+
| decimal | Decimal |
105+
| timestamp| Date |
106+
| string | string |
107+
| symbol | Symbol |
108+
| blob | Uint8Array |
109+
| clob | string |
110+
| struct | interface |
111+
| list | Array |
112+
| sexp | Array |
113+
114+
## Error Handling
115+
116+
The generated code includes comprehensive error handling:
117+
118+
- Schema validation errors
119+
- Type conversion errors
120+
- Serialization errors
121+
- Runtime validation errors
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"root": true,
3+
"parser": "@typescript-eslint/parser",
4+
"plugins": ["@typescript-eslint"],
5+
"extends": [
6+
"eslint:recommended",
7+
"plugin:@typescript-eslint/recommended",
8+
"plugin:@typescript-eslint/recommended-requiring-type-checking"
9+
],
10+
"parserOptions": {
11+
"project": "./tsconfig.json"
12+
},
13+
"rules": {
14+
"@typescript-eslint/explicit-function-return-type": "error",
15+
"@typescript-eslint/no-explicit-any": "error",
16+
"@typescript-eslint/no-unused-vars": "error",
17+
"@typescript-eslint/strict-boolean-expressions": "error"
18+
},
19+
"ignorePatterns": ["src/generated/**/*"]
20+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# TypeScript Code Generation Demo
2+
3+
This project demonstrates code generation using `ion-cli` with TypeScript as the target language. It uses the schema files from the parent directory and tests the generated code against both good and bad input files.
4+
5+
## Project Structure
6+
7+
```
8+
code-gen-demo/
9+
├── src/
10+
│ └── generated/ # Generated TypeScript code from schemas
11+
├── tests/
12+
│ └── roundtrip.test.ts # Roundtrip tests for generated code
13+
├── package.json
14+
└── tsconfig.json
15+
```
16+
17+
## Prerequisites
18+
19+
1. Install ion-cli:
20+
```bash
21+
brew install ion-cli
22+
# or
23+
cargo install ion-cli
24+
```
25+
26+
2. Set up environment:
27+
```bash
28+
export ION_CLI=/path/to/ion-cli # Optional, defaults to 'ion'
29+
export ION_INPUT=/path/to/input # Required for tests
30+
```
31+
32+
## Build Process
33+
34+
The build process is integrated with npm scripts:
35+
36+
1. `npm run generate` - Generates TypeScript code from schemas
37+
2. `npm run build` - Compiles TypeScript to JavaScript
38+
3. `npm test` - Runs the test suite
39+
40+
## Running Tests
41+
42+
The tests verify that the generated code can:
43+
- Read Ion data into TypeScript objects
44+
- Write TypeScript objects back to Ion format
45+
- Handle both valid and invalid input correctly
46+
47+
To run the tests:
48+
49+
```bash
50+
# From the code-gen-demo directory
51+
ION_INPUT=../../input npm test
52+
```
53+
54+
## Test Cases
55+
56+
1. Good Input Tests:
57+
- Struct with fields
58+
- Sequences
59+
- Enum types
60+
- Nested structures
61+
- Type annotations
62+
63+
2. Bad Input Tests:
64+
- Invalid struct fields
65+
- Invalid sequence elements
66+
- Invalid enum values
67+
- Type mismatches
68+
69+
## Generated Code Features
70+
71+
The generated TypeScript code includes:
72+
- Type-safe interfaces
73+
- Runtime type guards
74+
- Ion serialization/deserialization
75+
- Null safety
76+
- Type annotations support
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
{
2+
"name": "ion-cli-typescript-demo",
3+
"version": "1.0.0",
4+
"description": "TypeScript code generation demo for ion-cli",
5+
"scripts": {
6+
"pregenerate": "rimraf src/generated/*",
7+
"generate": "ion-cli generate -l typescript -d ../../schema -o ./src/generated",
8+
"prebuild": "npm run generate",
9+
"build": "tsc --noEmit && tsc",
10+
"lint": "eslint . --ext .ts",
11+
"pretest": "npm run build",
12+
"test": "jest --coverage",
13+
"clean": "rimraf dist src/generated/* coverage"
14+
},
15+
"dependencies": {
16+
"ion-js": "^4.3.0",
17+
"decimal.js": "^10.4.3"
18+
},
19+
"devDependencies": {
20+
"@types/jest": "^29.5.0",
21+
"@types/node": "^18.15.11",
22+
"@typescript-eslint/eslint-plugin": "^6.4.0",
23+
"@typescript-eslint/parser": "^6.4.0",
24+
"eslint": "^8.47.0",
25+
"jest": "^29.5.0",
26+
"rimraf": "^5.0.0",
27+
"ts-jest": "^29.1.0",
28+
"typescript": "^5.0.3"
29+
},
30+
"jest": {
31+
"preset": "ts-jest",
32+
"testEnvironment": "node",
33+
"roots": [
34+
"<rootDir>/src",
35+
"<rootDir>/tests"
36+
],
37+
"moduleNameMapper": {
38+
"@generated/(.*)": "<rootDir>/src/generated/$1"
39+
},
40+
"collectCoverageFrom": [
41+
"src/**/*.ts",
42+
"!src/generated/**/*.ts"
43+
],
44+
"coverageThreshold": {
45+
"global": {
46+
"branches": 80,
47+
"functions": 80,
48+
"lines": 80,
49+
"statements": 80
50+
}
51+
}
52+
}
53+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
2+
export enum EnumType {
3+
4+
5+
6+
FOO_BAR_BAZ = "FooBarBaz"
7+
8+
,
9+
BAR = "bar"
10+
11+
,
12+
BAZ = "baz"
13+
14+
,
15+
FOO = "foo"
16+
17+
}
18+
19+
export function isEnumType(value: any): value is EnumType {
20+
return Object.values(EnumType).includes(value);
21+
}
22+
23+
export class EnumTypeImpl implements IonSerializable {
24+
private value: EnumType;
25+
26+
constructor(value: EnumType) {
27+
this.value = value;
28+
}
29+
30+
public toIon(): any {
31+
const writer = makeWriter();
32+
writer.writeSymbol(this.value);
33+
return writer.getBytes();
34+
}
35+
36+
public static fromIon(reader: Reader): EnumType {
37+
const value = reader.stringValue();
38+
if (!value || !isEnumType(value)) {
39+
throw new Error(`Invalid enum value for EnumType: ${value}`);
40+
}
41+
return value as EnumType;
42+
}
43+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { makeReader, makeWriter, Reader, Writer, IonType } from 'ion-js';
2+
import { Decimal } from 'decimal.js';
3+
import { IonSymbol } from './serializers/symbol';
4+
import { IonTimestamp } from './serializers/timestamp';
5+
6+
export interface IonSerializable {
7+
toIon(): any;
8+
}
9+
10+
export const { LIST: ListType, STRUCT: StructType } = IonType;

0 commit comments

Comments
 (0)