@tsonic/tsbindgen 0.1.1 → 0.7.4
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/README.md +165 -366
- package/index.js +7 -6
- package/package.json +13 -9
- package/postinstall.js +71 -0
- package/bin.js +0 -51
package/README.md
CHANGED
|
@@ -1,405 +1,198 @@
|
|
|
1
1
|
# tsbindgen
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**TypeScript type declaration generator for .NET assemblies**
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
tsbindgen generates TypeScript declaration files (`.d.ts`) from .NET assemblies using reflection. It creates fully-typed, IDE-friendly TypeScript definitions that map the entire .NET Base Class Library (BCL) to TypeScript.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## Features
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
- **Complete BCL coverage** - Generates declarations for all 130 BCL namespaces, 4,296 types, and 50,675+ members
|
|
10
|
+
- **Zero TypeScript errors** - Output validates cleanly with `tsc --strict`
|
|
11
|
+
- **Branded primitives** - Type-safe numeric types (`int`, `long`, `decimal`, etc.) via `@tsonic/types`
|
|
12
|
+
- **Dual naming modes** - CLR PascalCase (`GetEnumerator`) or JavaScript camelCase (`getEnumerator`)
|
|
13
|
+
- **Generic type preservation** - Full generic type parameter support with constraints
|
|
14
|
+
- **Metadata sidecars** - CLR-specific information (static, virtual, override) in companion JSON files
|
|
15
|
+
- **Library mode** - Generate only your assembly's types, importing BCL types from a pre-existing package
|
|
10
16
|
|
|
11
|
-
|
|
17
|
+
## Installation
|
|
12
18
|
|
|
13
19
|
```bash
|
|
14
|
-
|
|
20
|
+
# Clone and build
|
|
21
|
+
git clone https://github.com/tsoniclang/tsbindgen
|
|
22
|
+
cd tsbindgen
|
|
23
|
+
dotnet build src/tsbindgen/tsbindgen.csproj
|
|
15
24
|
```
|
|
16
25
|
|
|
17
|
-
##
|
|
26
|
+
## Quick Start
|
|
18
27
|
|
|
19
|
-
###
|
|
28
|
+
### Generate BCL declarations
|
|
20
29
|
|
|
21
30
|
```bash
|
|
22
|
-
|
|
31
|
+
# Generate TypeScript declarations for .NET BCL
|
|
32
|
+
dotnet run --project src/tsbindgen/tsbindgen.csproj -- \
|
|
33
|
+
generate -d ~/.dotnet/shared/Microsoft.NETCore.App/10.0.0 \
|
|
34
|
+
-o ./output
|
|
23
35
|
```
|
|
24
36
|
|
|
25
|
-
|
|
37
|
+
### Generate for a custom assembly
|
|
26
38
|
|
|
27
39
|
```bash
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
40
|
+
# Generate for your own assembly
|
|
41
|
+
dotnet run --project src/tsbindgen/tsbindgen.csproj -- \
|
|
42
|
+
generate -a ./MyLibrary.dll \
|
|
43
|
+
-d ~/.dotnet/shared/Microsoft.NETCore.App/10.0.0 \
|
|
44
|
+
-o ./output
|
|
32
45
|
```
|
|
33
46
|
|
|
34
|
-
###
|
|
35
|
-
|
|
36
|
-
| Option | Short | Description | Default |
|
|
37
|
-
|--------|-------|-------------|---------|
|
|
38
|
-
| `--namespaces` | `-n` | Comma-separated list of namespaces to include | All namespaces |
|
|
39
|
-
| `--out-dir` | `-o` | Output directory for generated file | `.` (current directory) |
|
|
40
|
-
| `--log` | `-l` | Path to write JSON log file | None |
|
|
41
|
-
| `--config` | `-c` | Path to configuration JSON file | None |
|
|
42
|
-
|
|
43
|
-
### Examples
|
|
44
|
-
|
|
45
|
-
**Filter specific namespaces:**
|
|
47
|
+
### Library mode (exclude BCL types)
|
|
46
48
|
|
|
47
49
|
```bash
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
**Specify output directory:**
|
|
50
|
+
# First, generate BCL types
|
|
51
|
+
dotnet run -- generate -d $DOTNET_RUNTIME -o ./bcl-types
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
|
|
53
|
+
# Then generate your library, importing BCL from the pre-existing package
|
|
54
|
+
dotnet run -- generate -a ./MyLibrary.dll -d $DOTNET_RUNTIME -o ./my-lib --lib ./bcl-types
|
|
55
55
|
```
|
|
56
56
|
|
|
57
|
-
|
|
57
|
+
## CLI Reference
|
|
58
58
|
|
|
59
|
-
|
|
60
|
-
tsbindgen System.IO.dll --log build.log.json
|
|
61
|
-
```
|
|
59
|
+
### Commands
|
|
62
60
|
|
|
63
|
-
|
|
61
|
+
| Command | Description |
|
|
62
|
+
|---------|-------------|
|
|
63
|
+
| `generate` | Generate TypeScript declarations from .NET assemblies |
|
|
64
64
|
|
|
65
|
-
|
|
66
|
-
# Step 1: Generate BCL package (once)
|
|
67
|
-
tsbindgen generate -d ~/dotnet/shared/Microsoft.NETCore.App/10.0.0 -o ./bcl-package
|
|
65
|
+
### Generate Options
|
|
68
66
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
2. Use `--lib <base-package-path>` when generating user library
|
|
81
|
-
3. tsbindgen filters: keeps types NOT in base, removes types IN base
|
|
82
|
-
4. Validates no dangling references (LIB002 strict check)
|
|
83
|
-
|
|
84
|
-
**Use case:** Publishing TypeScript declarations for a .NET library without duplicating BCL type definitions.
|
|
85
|
-
|
|
86
|
-
See [CLI documentation](spec/cli.md#library-mode) for complete details.
|
|
87
|
-
|
|
88
|
-
## Generated Output
|
|
89
|
-
|
|
90
|
-
The tool generates two files for each assembly:
|
|
91
|
-
|
|
92
|
-
1. **TypeScript declarations** (`.d.ts`) - TypeScript type definitions
|
|
93
|
-
2. **Metadata sidecar** (`.metadata.json`) - C# semantic information
|
|
94
|
-
|
|
95
|
-
### TypeScript Declarations
|
|
96
|
-
|
|
97
|
-
The `.d.ts` file contains TypeScript declarations with:
|
|
98
|
-
|
|
99
|
-
1. **Branded type aliases** for C# numeric types:
|
|
100
|
-
```typescript
|
|
101
|
-
type int = number & { __brand: "int" };
|
|
102
|
-
type decimal = number & { __brand: "decimal" };
|
|
103
|
-
// ... etc
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
2. **Namespace declarations** matching .NET namespaces:
|
|
107
|
-
```typescript
|
|
108
|
-
declare namespace System.Text.Json {
|
|
109
|
-
class JsonSerializer {
|
|
110
|
-
static Serialize<T>(value: T): string;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
3. **Proper type mappings**:
|
|
116
|
-
- `System.String` → `string`
|
|
117
|
-
- `System.Int32` → `int`
|
|
118
|
-
- `System.Boolean` → `boolean`
|
|
119
|
-
- `Task<T>` → `Promise<T>`
|
|
120
|
-
- `T[]` → `ReadonlyArray<T>`
|
|
121
|
-
- `List<T>` → `List<T>`
|
|
122
|
-
- `Nullable<T>` → `T | null`
|
|
123
|
-
|
|
124
|
-
### Metadata Sidecar Files
|
|
125
|
-
|
|
126
|
-
The `.metadata.json` file contains C# semantic information that TypeScript cannot express. This enables the Tsonic compiler to generate correct C# code, particularly for:
|
|
127
|
-
|
|
128
|
-
- **Virtual/override methods** - Required to correctly override base class methods
|
|
129
|
-
- **Abstract classes/methods** - Required to properly extend abstract types
|
|
130
|
-
- **Sealed classes/methods** - Prevents invalid inheritance
|
|
131
|
-
- **Static classes** - Type-level restrictions
|
|
132
|
-
- **Struct vs Class** - Value vs reference type semantics
|
|
133
|
-
- **Method accessibility** - Public, protected, private, internal modifiers
|
|
134
|
-
|
|
135
|
-
#### Example Structure
|
|
136
|
-
|
|
137
|
-
```json
|
|
138
|
-
{
|
|
139
|
-
"assemblyName": "System.Text.Json",
|
|
140
|
-
"assemblyVersion": "10.0.0.0",
|
|
141
|
-
"types": {
|
|
142
|
-
"System.Text.Json.JsonSerializer": {
|
|
143
|
-
"kind": "class",
|
|
144
|
-
"isAbstract": true,
|
|
145
|
-
"isSealed": false,
|
|
146
|
-
"isStatic": false,
|
|
147
|
-
"baseType": null,
|
|
148
|
-
"interfaces": [],
|
|
149
|
-
"members": {
|
|
150
|
-
"Serialize<T>(T)": {
|
|
151
|
-
"kind": "method",
|
|
152
|
-
"isVirtual": false,
|
|
153
|
-
"isAbstract": false,
|
|
154
|
-
"isSealed": false,
|
|
155
|
-
"isOverride": false,
|
|
156
|
-
"isStatic": true,
|
|
157
|
-
"accessibility": "public"
|
|
158
|
-
},
|
|
159
|
-
"Deserialize<T>(string)": {
|
|
160
|
-
"kind": "method",
|
|
161
|
-
"isVirtual": false,
|
|
162
|
-
"isAbstract": false,
|
|
163
|
-
"isSealed": false,
|
|
164
|
-
"isOverride": false,
|
|
165
|
-
"isStatic": true,
|
|
166
|
-
"accessibility": "public"
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
#### Metadata Fields
|
|
175
|
-
|
|
176
|
-
**Type-level fields:**
|
|
177
|
-
- `kind`: `"class"`, `"struct"`, `"interface"`, or `"enum"`
|
|
178
|
-
- `isAbstract`: True for abstract classes (excluding interfaces)
|
|
179
|
-
- `isSealed`: True for sealed classes (excluding value types and enums)
|
|
180
|
-
- `isStatic`: True for static classes
|
|
181
|
-
- `baseType`: Full name of base class (if any)
|
|
182
|
-
- `interfaces`: Array of implemented interface names
|
|
183
|
-
- `members`: Dictionary of member metadata keyed by signature
|
|
184
|
-
|
|
185
|
-
**Member-level fields:**
|
|
186
|
-
- `kind`: `"method"`, `"property"`, or `"constructor"`
|
|
187
|
-
- `isVirtual`: True if method can be overridden
|
|
188
|
-
- `isAbstract`: True for abstract methods
|
|
189
|
-
- `isSealed`: True if method prevents further overriding
|
|
190
|
-
- `isOverride`: True if method overrides a base method
|
|
191
|
-
- `isStatic`: True for static members
|
|
192
|
-
- `accessibility`: `"public"`, `"protected"`, `"private"`, `"internal"`, etc.
|
|
193
|
-
|
|
194
|
-
**Signature format:**
|
|
195
|
-
- Methods: `MethodName(Type1,Type2,...)` using C# type names
|
|
196
|
-
- Properties: `PropertyName`
|
|
197
|
-
- Constructors: `ctor(Type1,Type2,...)`
|
|
198
|
-
|
|
199
|
-
## Configuration File
|
|
200
|
-
|
|
201
|
-
You can provide a JSON configuration file to customize behavior:
|
|
202
|
-
|
|
203
|
-
```json
|
|
204
|
-
{
|
|
205
|
-
"skipNamespaces": ["System.Internal"],
|
|
206
|
-
"typeRenames": {
|
|
207
|
-
"System.OldType": "NewType"
|
|
208
|
-
},
|
|
209
|
-
"skipMembers": [
|
|
210
|
-
"System.String::InternalMethod"
|
|
211
|
-
]
|
|
212
|
-
}
|
|
213
|
-
```
|
|
67
|
+
| Option | Short | Description | Default |
|
|
68
|
+
|--------|-------|-------------|---------|
|
|
69
|
+
| `--assembly` | `-a` | Path to assembly file(s) to process | - |
|
|
70
|
+
| `--assembly-dir` | `-d` | Directory containing .NET runtime assemblies | - |
|
|
71
|
+
| `--out-dir` | `-o` | Output directory for generated files | `out` |
|
|
72
|
+
| `--namespaces` | `-n` | Comma-separated namespace filter | (all) |
|
|
73
|
+
| `--naming` | - | Naming convention: `js` (camelCase) or `clr` (PascalCase) | `clr` |
|
|
74
|
+
| `--lib` | - | Path to pre-existing BCL types (library mode) | - |
|
|
75
|
+
| `--verbose` | `-v` | Enable detailed progress output | false |
|
|
76
|
+
| `--logs` | - | Enable specific log categories (comma-separated) | - |
|
|
77
|
+
| `--strict` | - | Enable strict mode validation | false |
|
|
214
78
|
|
|
215
|
-
|
|
79
|
+
### Examples
|
|
216
80
|
|
|
217
81
|
```bash
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
## Log Output
|
|
222
|
-
|
|
223
|
-
When using `--log`, a JSON file is generated with:
|
|
224
|
-
|
|
225
|
-
```json
|
|
226
|
-
{
|
|
227
|
-
"timestamp": "2025-11-01T13:03:38Z",
|
|
228
|
-
"namespaces": ["System.Text.Json"],
|
|
229
|
-
"typeCounts": {
|
|
230
|
-
"classes": 40,
|
|
231
|
-
"interfaces": 5,
|
|
232
|
-
"enums": 10,
|
|
233
|
-
"total": 55
|
|
234
|
-
},
|
|
235
|
-
"warnings": []
|
|
236
|
-
}
|
|
237
|
-
```
|
|
238
|
-
|
|
239
|
-
## Type Mapping Rules
|
|
240
|
-
|
|
241
|
-
The tool follows Tsonic's type mapping specification:
|
|
242
|
-
|
|
243
|
-
- **Classes** → TypeScript classes
|
|
244
|
-
- **Interfaces** → TypeScript interfaces
|
|
245
|
-
- **Enums** → TypeScript enums
|
|
246
|
-
- **Structs** → TypeScript classes
|
|
247
|
-
- **Static methods** → `static` methods
|
|
248
|
-
- **Properties** → TypeScript properties (with `readonly` when appropriate)
|
|
249
|
-
- **Generic types** → TypeScript generics `<T>`
|
|
250
|
-
- **Optional parameters** → `param?: Type`
|
|
251
|
-
- **Params arrays** → `...values: ReadonlyArray<T>`
|
|
252
|
-
|
|
253
|
-
## Excluded Members
|
|
82
|
+
# Generate BCL with JavaScript naming
|
|
83
|
+
dotnet run -- generate -d $DOTNET_RUNTIME -o ./out --naming js
|
|
254
84
|
|
|
255
|
-
|
|
85
|
+
# Generate specific namespaces only
|
|
86
|
+
dotnet run -- generate -d $DOTNET_RUNTIME -o ./out -n System,System.Collections.Generic
|
|
256
87
|
|
|
257
|
-
|
|
258
|
-
-
|
|
259
|
-
- Common Object methods (`Equals`, `GetHashCode`, `ToString`, `GetType`, `ReferenceEquals`)
|
|
260
|
-
- Special-name members (property accessors, backing fields)
|
|
88
|
+
# Verbose output with specific log categories
|
|
89
|
+
dotnet run -- generate -d $DOTNET_RUNTIME -o ./out -v --logs ImportPlanner,FacadeEmitter
|
|
261
90
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
Parameter names that conflict with TypeScript/JavaScript reserved keywords are automatically escaped by prefixing them with an underscore. This prevents syntax errors in the generated declarations.
|
|
265
|
-
|
|
266
|
-
**Escaped keywords include:**
|
|
267
|
-
- Control flow: `break`, `case`, `catch`, `continue`, `default`, `do`, `else`, `finally`, `for`, `if`, `return`, `switch`, `throw`, `try`, `while`
|
|
268
|
-
- Declarations: `class`, `const`, `enum`, `export`, `extends`, `function`, `import`, `let`, `var`, `void`
|
|
269
|
-
- Modifiers: `async`, `await`, `implements`, `interface`, `package`, `private`, `protected`, `public`, `static`, `yield`
|
|
270
|
-
- Special identifiers: `arguments`, `eval`, `this`, `super`, `new`, `typeof`, `instanceof`, `delete`, `debugger`, `with`, `in`
|
|
271
|
-
|
|
272
|
-
**Example:**
|
|
273
|
-
```csharp
|
|
274
|
-
// C# method signature
|
|
275
|
-
public static LoopExpression Loop(Expression body, LabelTarget break, LabelTarget continue)
|
|
276
|
-
|
|
277
|
-
// Generated TypeScript
|
|
278
|
-
static Loop(body: Expression, _break: LabelTarget, _continue: LabelTarget): LoopExpression;
|
|
91
|
+
# Strict mode (additional validation)
|
|
92
|
+
dotnet run -- generate -d $DOTNET_RUNTIME -o ./out --strict
|
|
279
93
|
```
|
|
280
94
|
|
|
281
|
-
|
|
95
|
+
## Output Structure
|
|
282
96
|
|
|
283
|
-
|
|
97
|
+
For each namespace, tsbindgen generates:
|
|
284
98
|
|
|
285
|
-
The project includes comprehensive test scripts to ensure correctness and prevent regressions.
|
|
286
|
-
|
|
287
|
-
### Running All Tests
|
|
288
|
-
|
|
289
|
-
```bash
|
|
290
|
-
# TypeScript syntax validation
|
|
291
|
-
npm install # First time only
|
|
292
|
-
npm run validate
|
|
293
|
-
|
|
294
|
-
# Regression guards (run all)
|
|
295
|
-
./scripts/test-determinism.sh # Deterministic output
|
|
296
|
-
./scripts/test-strict-mode.sh # Strict mode compliance
|
|
297
|
-
./scripts/test-surface-manifest.sh # Surface baseline guard
|
|
298
|
-
./scripts/test-lib.sh # Library mode (--lib)
|
|
299
99
|
```
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
100
|
+
output/
|
|
101
|
+
├── System/
|
|
102
|
+
│ ├── index.d.ts # Public facade (imports + re-exports)
|
|
103
|
+
│ └── internal/
|
|
104
|
+
│ └── index.d.ts # Type declarations
|
|
105
|
+
├── System.Collections.Generic/
|
|
106
|
+
│ ├── index.d.ts
|
|
107
|
+
│ └── internal/
|
|
108
|
+
│ └── index.d.ts
|
|
109
|
+
└── ... (130 namespaces)
|
|
307
110
|
```
|
|
308
111
|
|
|
309
|
-
|
|
310
|
-
1. Regenerates all 38 BCL assemblies to a temporary directory
|
|
311
|
-
2. Creates an `index.d.ts` with triple-slash references
|
|
312
|
-
3. Runs the TypeScript compiler to validate all declarations
|
|
313
|
-
4. Reports syntax errors (TS1xxx), duplicate type errors (TS6200), and semantic errors (TS2xxx)
|
|
112
|
+
### Output Files
|
|
314
113
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
114
|
+
| File | Description |
|
|
115
|
+
|------|-------------|
|
|
116
|
+
| `index.d.ts` | Public facade with imports and friendly re-exports |
|
|
117
|
+
| `internal/index.d.ts` | Full type declarations with $instance pattern |
|
|
318
118
|
|
|
319
|
-
|
|
320
|
-
```
|
|
321
|
-
✓ VALIDATION PASSED
|
|
119
|
+
## Type Mapping
|
|
322
120
|
|
|
323
|
-
|
|
324
|
-
All metadata files present
|
|
325
|
-
✓ No TypeScript syntax errors (TS1xxx)
|
|
121
|
+
### Primitive Types
|
|
326
122
|
|
|
327
|
-
|
|
328
|
-
- Syntax errors (TS1xxx): 0 ✓
|
|
329
|
-
- Duplicate types (TS6200): 0 (expected)
|
|
330
|
-
- Semantic errors (TS2xxx): 1 (expected - missing cross-assembly refs)
|
|
331
|
-
```
|
|
123
|
+
CLR primitive types map to branded TypeScript types from `@tsonic/types`:
|
|
332
124
|
|
|
333
|
-
|
|
125
|
+
| CLR Type | TypeScript Type |
|
|
126
|
+
|----------|----------------|
|
|
127
|
+
| `System.Int32` | `int` |
|
|
128
|
+
| `System.Int64` | `long` |
|
|
129
|
+
| `System.Single` | `float` |
|
|
130
|
+
| `System.Double` | `double` |
|
|
131
|
+
| `System.Decimal` | `decimal` |
|
|
132
|
+
| `System.Byte` | `byte` |
|
|
133
|
+
| `System.Boolean` | `boolean` |
|
|
134
|
+
| `System.String` | `string` |
|
|
135
|
+
| `System.Char` | `char` |
|
|
334
136
|
|
|
335
|
-
|
|
137
|
+
### Generic Types
|
|
336
138
|
|
|
337
|
-
|
|
139
|
+
Generic types use underscore suffix for arity:
|
|
338
140
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
141
|
+
| CLR Type | TypeScript Type |
|
|
142
|
+
|----------|----------------|
|
|
143
|
+
| `List<T>` | `List_1<T>` |
|
|
144
|
+
| `Dictionary<TKey, TValue>` | `Dictionary_2<TKey, TValue>` |
|
|
145
|
+
| `Func<T, TResult>` | `Func_2<T, TResult>` |
|
|
342
146
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
#### Strict Mode Test (`test-strict-mode.sh`)
|
|
349
|
-
|
|
350
|
-
Verifies strict mode compliance and performance baseline:
|
|
351
|
-
|
|
352
|
-
```bash
|
|
353
|
-
./scripts/test-strict-mode.sh
|
|
147
|
+
Friendly aliases are also exported:
|
|
148
|
+
```typescript
|
|
149
|
+
// Both work:
|
|
150
|
+
import { List_1 } from "@tsonic/dotnet/System.Collections.Generic";
|
|
151
|
+
import { List } from "@tsonic/dotnet/System.Collections.Generic"; // Friendly alias
|
|
354
152
|
```
|
|
355
153
|
|
|
356
|
-
|
|
357
|
-
- No diagnostics with `--strict` flag
|
|
358
|
-
- Performance doesn't regress beyond baseline
|
|
154
|
+
### Type Kind Mapping
|
|
359
155
|
|
|
360
|
-
|
|
156
|
+
| CLR Kind | TypeScript Pattern |
|
|
157
|
+
|----------|-------------------|
|
|
158
|
+
| Class | `interface + const` (instance + static sides) |
|
|
159
|
+
| Struct | `interface + const` |
|
|
160
|
+
| Interface | `interface` |
|
|
161
|
+
| Enum | `const enum` |
|
|
162
|
+
| Delegate | `type` (function signature + CLR type intersection) |
|
|
163
|
+
| Static class | `abstract class` (static methods only) |
|
|
361
164
|
|
|
362
|
-
|
|
165
|
+
## Naming Conventions
|
|
363
166
|
|
|
364
|
-
|
|
365
|
-
|
|
167
|
+
### Default (CLR) Naming
|
|
168
|
+
```typescript
|
|
169
|
+
list.GetEnumerator(); // PascalCase
|
|
170
|
+
console.WriteLine(); // PascalCase
|
|
366
171
|
```
|
|
367
172
|
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
#### Library Mode Test (`test-lib.sh`)
|
|
173
|
+
### JavaScript Naming (`--naming js`)
|
|
174
|
+
```typescript
|
|
175
|
+
list.getEnumerator(); // camelCase
|
|
176
|
+
console.writeLine(); // camelCase
|
|
177
|
+
```
|
|
374
178
|
|
|
375
|
-
|
|
179
|
+
## Testing
|
|
376
180
|
|
|
377
181
|
```bash
|
|
378
|
-
|
|
379
|
-
|
|
182
|
+
# Run all regression tests
|
|
183
|
+
bash test/scripts/run-all.sh
|
|
380
184
|
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
- User library builds successfully
|
|
384
|
-
- Full generation includes both user + BCL types
|
|
385
|
-
- `--lib` filtered generation includes ONLY user types
|
|
386
|
-
- No LIB001-003 validation errors
|
|
387
|
-
- BCL namespaces correctly excluded from filtered output
|
|
388
|
-
- User namespaces correctly included in filtered output
|
|
185
|
+
# Run validation (TypeScript compilation check)
|
|
186
|
+
node test/validate/validate.js
|
|
389
187
|
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
✓ Filtered generation: 1 namespaces (user only)
|
|
399
|
-
✓ BCL types correctly excluded via --lib
|
|
400
|
-
✓ User types (MyCompany.Utils) correctly included
|
|
401
|
-
✓ No LIB001-003 validation errors
|
|
402
|
-
✓ Strict mode passes
|
|
188
|
+
# Run completeness verification
|
|
189
|
+
node test/validate/verify-completeness.js
|
|
190
|
+
|
|
191
|
+
# Individual tests
|
|
192
|
+
bash test/scripts/test-strict-mode.sh
|
|
193
|
+
bash test/scripts/test-determinism.sh
|
|
194
|
+
bash test/scripts/test-surface-manifest.sh
|
|
195
|
+
bash test/scripts/test-lib.sh
|
|
403
196
|
```
|
|
404
197
|
|
|
405
198
|
## Development
|
|
@@ -408,41 +201,47 @@ Summary:
|
|
|
408
201
|
|
|
409
202
|
```
|
|
410
203
|
tsbindgen/
|
|
411
|
-
├──
|
|
412
|
-
│ ├──
|
|
413
|
-
│ ├──
|
|
414
|
-
│ ├──
|
|
415
|
-
│ ├──
|
|
416
|
-
│ ├──
|
|
417
|
-
│ ├──
|
|
418
|
-
│ ├──
|
|
419
|
-
│
|
|
420
|
-
|
|
421
|
-
│
|
|
422
|
-
├──
|
|
423
|
-
│
|
|
424
|
-
|
|
425
|
-
└──
|
|
204
|
+
├── src/tsbindgen/
|
|
205
|
+
│ ├── Cli/ # Command-line interface
|
|
206
|
+
│ ├── Load/ # Assembly loading and reflection
|
|
207
|
+
│ ├── Model/ # Symbol graph data structures
|
|
208
|
+
│ ├── Shape/ # Type transformation passes
|
|
209
|
+
│ ├── Normalize/ # Name reservation
|
|
210
|
+
│ ├── Plan/ # Import/export planning
|
|
211
|
+
│ ├── Emit/ # TypeScript file generation
|
|
212
|
+
│ └── Renaming/ # Name conflict resolution
|
|
213
|
+
├── test/
|
|
214
|
+
│ ├── scripts/ # Test scripts
|
|
215
|
+
│ ├── validate/ # Validation scripts
|
|
216
|
+
│ ├── baselines/ # Surface manifest baseline
|
|
217
|
+
│ └── fixtures/ # Test fixtures
|
|
218
|
+
└── docs/ # Documentation
|
|
426
219
|
```
|
|
427
220
|
|
|
428
|
-
###
|
|
221
|
+
### Build Commands
|
|
429
222
|
|
|
430
223
|
```bash
|
|
431
|
-
|
|
432
|
-
|
|
224
|
+
# Build
|
|
225
|
+
dotnet build src/tsbindgen/tsbindgen.csproj
|
|
433
226
|
|
|
434
|
-
|
|
227
|
+
# Build release
|
|
228
|
+
dotnet build src/tsbindgen/tsbindgen.csproj -c Release
|
|
435
229
|
|
|
436
|
-
|
|
437
|
-
dotnet run --project
|
|
230
|
+
# Run
|
|
231
|
+
dotnet run --project src/tsbindgen/tsbindgen.csproj -- <args>
|
|
438
232
|
```
|
|
439
233
|
|
|
440
|
-
##
|
|
234
|
+
## Documentation
|
|
235
|
+
|
|
236
|
+
- [User Guide](docs/user-guide.md) - Detailed usage instructions
|
|
237
|
+
- [Architecture](docs/architecture/) - Internal architecture documentation
|
|
238
|
+
|
|
239
|
+
## Related Projects
|
|
441
240
|
|
|
442
|
-
- [
|
|
443
|
-
- [
|
|
444
|
-
- [
|
|
241
|
+
- **[@tsonic/dotnet](https://www.npmjs.com/package/@tsonic/dotnet)** - Pre-generated BCL types with JavaScript naming
|
|
242
|
+
- **[@tsonic/dotnet-pure](https://www.npmjs.com/package/@tsonic/dotnet-pure)** - Pre-generated BCL types with CLR naming
|
|
243
|
+
- **[@tsonic/types](https://www.npmjs.com/package/@tsonic/types)** - Branded primitive types
|
|
445
244
|
|
|
446
245
|
## License
|
|
447
246
|
|
|
448
|
-
|
|
247
|
+
MIT
|
package/index.js
CHANGED
|
@@ -10,10 +10,10 @@ import { fileURLToPath } from "node:url";
|
|
|
10
10
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
11
11
|
|
|
12
12
|
const PLATFORMS = {
|
|
13
|
-
"darwin-arm64": "
|
|
14
|
-
"darwin-x64": "
|
|
15
|
-
"linux-arm64": "
|
|
16
|
-
"linux-x64": "
|
|
13
|
+
"darwin-arm64": "tsbindgen-darwin-arm64",
|
|
14
|
+
"darwin-x64": "tsbindgen-darwin-x64",
|
|
15
|
+
"linux-arm64": "tsbindgen-linux-arm64",
|
|
16
|
+
"linux-x64": "tsbindgen-linux-x64",
|
|
17
17
|
};
|
|
18
18
|
|
|
19
19
|
const getPlatformKey = () => `${process.platform}-${process.arch}`;
|
|
@@ -34,8 +34,9 @@ export const getBinaryPath = () => {
|
|
|
34
34
|
|
|
35
35
|
const binaryName = "tsbindgen";
|
|
36
36
|
const paths = [
|
|
37
|
-
join(__dirname, "node_modules", packageName, binaryName),
|
|
37
|
+
join(__dirname, "node_modules", "@tsonic", packageName, binaryName),
|
|
38
38
|
join(__dirname, "..", packageName, binaryName),
|
|
39
|
+
join(__dirname, "..", "..", "@tsonic", packageName, binaryName),
|
|
39
40
|
];
|
|
40
41
|
|
|
41
42
|
for (const p of paths) {
|
|
@@ -46,7 +47,7 @@ export const getBinaryPath = () => {
|
|
|
46
47
|
|
|
47
48
|
throw new Error(
|
|
48
49
|
`Could not find tsbindgen binary for ${key}. ` +
|
|
49
|
-
`Package
|
|
50
|
+
`Package @tsonic/${packageName} may not be installed.`
|
|
50
51
|
);
|
|
51
52
|
};
|
|
52
53
|
|
package/package.json
CHANGED
|
@@ -1,28 +1,29 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tsonic/tsbindgen",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.4",
|
|
4
4
|
"description": "Generate TypeScript declarations from .NET assemblies",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
|
-
"tsbindgen": "./bin
|
|
7
|
+
"tsbindgen": "./bin/tsbindgen"
|
|
8
8
|
},
|
|
9
9
|
"main": "./index.js",
|
|
10
10
|
"exports": {
|
|
11
11
|
".": "./index.js"
|
|
12
12
|
},
|
|
13
13
|
"files": [
|
|
14
|
-
"
|
|
14
|
+
"postinstall.js",
|
|
15
15
|
"index.js",
|
|
16
16
|
"README.md"
|
|
17
17
|
],
|
|
18
18
|
"scripts": {
|
|
19
|
-
"build": "./scripts/build-native.sh"
|
|
19
|
+
"build": "./scripts/build-native.sh",
|
|
20
|
+
"postinstall": "node postinstall.js"
|
|
20
21
|
},
|
|
21
22
|
"optionalDependencies": {
|
|
22
|
-
"@tsonic/tsbindgen-darwin-arm64": "0.
|
|
23
|
-
"@tsonic/tsbindgen-darwin-x64": "0.
|
|
24
|
-
"@tsonic/tsbindgen-linux-arm64": "0.
|
|
25
|
-
"@tsonic/tsbindgen-linux-x64": "0.
|
|
23
|
+
"@tsonic/tsbindgen-darwin-arm64": "0.7.4",
|
|
24
|
+
"@tsonic/tsbindgen-darwin-x64": "0.7.4",
|
|
25
|
+
"@tsonic/tsbindgen-linux-arm64": "0.7.4",
|
|
26
|
+
"@tsonic/tsbindgen-linux-x64": "0.7.4"
|
|
26
27
|
},
|
|
27
28
|
"keywords": [
|
|
28
29
|
"tsonic",
|
|
@@ -36,6 +37,9 @@
|
|
|
36
37
|
"license": "MIT",
|
|
37
38
|
"repository": {
|
|
38
39
|
"type": "git",
|
|
39
|
-
"url": "https://github.com/tsoniclang/tsbindgen.git"
|
|
40
|
+
"url": "git+https://github.com/tsoniclang/tsbindgen.git"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"typescript": "^5.9.3"
|
|
40
44
|
}
|
|
41
45
|
}
|
package/postinstall.js
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { existsSync, mkdirSync, symlinkSync, unlinkSync, chmodSync } from "node:fs";
|
|
4
|
+
import { dirname, join } from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
|
|
7
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
8
|
+
|
|
9
|
+
const PLATFORMS = {
|
|
10
|
+
"darwin-arm64": "tsbindgen-darwin-arm64",
|
|
11
|
+
"darwin-x64": "tsbindgen-darwin-x64",
|
|
12
|
+
"linux-arm64": "tsbindgen-linux-arm64",
|
|
13
|
+
"linux-x64": "tsbindgen-linux-x64",
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const getPlatformKey = () => `${process.platform}-${process.arch}`;
|
|
17
|
+
|
|
18
|
+
const findBinary = () => {
|
|
19
|
+
const key = getPlatformKey();
|
|
20
|
+
const packageName = PLATFORMS[key];
|
|
21
|
+
|
|
22
|
+
if (!packageName) {
|
|
23
|
+
console.error(`tsbindgen: Unsupported platform: ${key}`);
|
|
24
|
+
console.error("Supported: darwin-arm64, darwin-x64, linux-arm64, linux-x64");
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const binaryName = "tsbindgen";
|
|
29
|
+
|
|
30
|
+
// Search paths for the platform-specific binary
|
|
31
|
+
const paths = [
|
|
32
|
+
// Nested in this package's node_modules
|
|
33
|
+
join(__dirname, "node_modules", "@tsonic", packageName, binaryName),
|
|
34
|
+
// Sibling in @tsonic scope (hoisted)
|
|
35
|
+
join(__dirname, "..", packageName, binaryName),
|
|
36
|
+
// At root node_modules level
|
|
37
|
+
join(__dirname, "..", "..", "@tsonic", packageName, binaryName),
|
|
38
|
+
];
|
|
39
|
+
|
|
40
|
+
for (const p of paths) {
|
|
41
|
+
if (existsSync(p)) {
|
|
42
|
+
return p;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
console.error(`tsbindgen: Could not find binary for ${key}`);
|
|
47
|
+
console.error(`Package @tsonic/${packageName} may not be installed.`);
|
|
48
|
+
process.exit(1);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
// Create bin directory if needed
|
|
52
|
+
const binDir = join(__dirname, "bin");
|
|
53
|
+
if (!existsSync(binDir)) {
|
|
54
|
+
mkdirSync(binDir);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Find the platform binary
|
|
58
|
+
const binaryPath = findBinary();
|
|
59
|
+
|
|
60
|
+
// Create symlink
|
|
61
|
+
const symlinkPath = join(binDir, "tsbindgen");
|
|
62
|
+
|
|
63
|
+
// Remove existing symlink if present
|
|
64
|
+
if (existsSync(symlinkPath)) {
|
|
65
|
+
unlinkSync(symlinkPath);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
symlinkSync(binaryPath, symlinkPath);
|
|
69
|
+
chmodSync(symlinkPath, 0o755);
|
|
70
|
+
|
|
71
|
+
console.log(`tsbindgen: Linked to ${binaryPath}`);
|
package/bin.js
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import { spawnSync } from "node:child_process";
|
|
4
|
-
import { existsSync } from "node:fs";
|
|
5
|
-
import { dirname, join } from "node:path";
|
|
6
|
-
import { fileURLToPath } from "node:url";
|
|
7
|
-
|
|
8
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
9
|
-
|
|
10
|
-
const PLATFORMS = {
|
|
11
|
-
"darwin-arm64": "@tsonic/tsbindgen-darwin-arm64",
|
|
12
|
-
"darwin-x64": "@tsonic/tsbindgen-darwin-x64",
|
|
13
|
-
"linux-arm64": "@tsonic/tsbindgen-linux-arm64",
|
|
14
|
-
"linux-x64": "@tsonic/tsbindgen-linux-x64",
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
const getPlatformKey = () => `${process.platform}-${process.arch}`;
|
|
18
|
-
|
|
19
|
-
const findBinary = () => {
|
|
20
|
-
const key = getPlatformKey();
|
|
21
|
-
const packageName = PLATFORMS[key];
|
|
22
|
-
|
|
23
|
-
if (!packageName) {
|
|
24
|
-
console.error(`Unsupported platform: ${key}`);
|
|
25
|
-
console.error("tsbindgen supports: darwin-arm64, darwin-x64, linux-arm64, linux-x64");
|
|
26
|
-
process.exit(1);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const binaryName = "tsbindgen";
|
|
30
|
-
const paths = [
|
|
31
|
-
join(__dirname, "node_modules", packageName, binaryName),
|
|
32
|
-
join(__dirname, "..", packageName, binaryName),
|
|
33
|
-
];
|
|
34
|
-
|
|
35
|
-
for (const p of paths) {
|
|
36
|
-
if (existsSync(p)) {
|
|
37
|
-
return p;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
console.error(`Could not find tsbindgen binary for ${key}`);
|
|
42
|
-
console.error(`Package ${packageName} may not be installed.`);
|
|
43
|
-
process.exit(1);
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
const binaryPath = findBinary();
|
|
47
|
-
const result = spawnSync(binaryPath, process.argv.slice(2), {
|
|
48
|
-
stdio: "inherit",
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
process.exit(result.status ?? 1);
|