@siyavuyachagi/typesharp 0.1.1 β†’ 0.1.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.
Files changed (43) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +118 -43
  3. package/dist/cli/index.js +6 -4
  4. package/dist/cli/index.js.map +1 -1
  5. package/dist/core/create-sample-config.d.ts +5 -0
  6. package/dist/core/create-sample-config.d.ts.map +1 -0
  7. package/dist/core/create-sample-config.js +110 -0
  8. package/dist/core/create-sample-config.js.map +1 -0
  9. package/dist/core/index.d.ts +5 -5
  10. package/dist/core/index.d.ts.map +1 -1
  11. package/dist/core/index.js +36 -66
  12. package/dist/core/index.js.map +1 -1
  13. package/dist/generator/index.d.ts.map +1 -1
  14. package/dist/generator/index.js +5 -4
  15. package/dist/generator/index.js.map +1 -1
  16. package/dist/index.d.ts +1 -1
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +1 -2
  19. package/dist/index.js.map +1 -1
  20. package/dist/parser/index.d.ts.map +1 -1
  21. package/dist/parser/index.js +12 -190
  22. package/dist/parser/index.js.map +1 -1
  23. package/dist/parser/parse-properties.d.ts +6 -0
  24. package/dist/parser/parse-properties.d.ts.map +1 -0
  25. package/dist/parser/parse-properties.js +250 -0
  26. package/dist/parser/parse-properties.js.map +1 -0
  27. package/dist/parser/resolve-project-files-from-source.d.ts +29 -0
  28. package/dist/parser/resolve-project-files-from-source.d.ts.map +1 -0
  29. package/dist/parser/resolve-project-files-from-source.js +98 -0
  30. package/dist/parser/resolve-project-files-from-source.js.map +1 -0
  31. package/dist/types/index.d.ts +7 -2
  32. package/dist/types/index.d.ts.map +1 -1
  33. package/dist/types/naming-convention-config.d.ts +9 -0
  34. package/dist/types/naming-convention-config.d.ts.map +1 -0
  35. package/dist/types/naming-convention-config.js +3 -0
  36. package/dist/types/naming-convention-config.js.map +1 -0
  37. package/dist/types/naming-convention.d.ts +5 -0
  38. package/dist/types/naming-convention.d.ts.map +1 -0
  39. package/dist/types/naming-convention.js +3 -0
  40. package/dist/types/naming-convention.js.map +1 -0
  41. package/dist/types/typesharp-config.d.ts +18 -25
  42. package/dist/types/typesharp-config.d.ts.map +1 -1
  43. package/package.json +13 -6
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2024 Siyavuya Chagi
3
+ Copyright (c) 2025 Siyavuya Chagi
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -1,42 +1,49 @@
1
1
  # TypeSharp
2
2
 
3
3
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
4
- [![npm version](https://img.shields.io/npm/v/@siyavuyachagi/typesharp.svg)](https://www.npmjs.com/package/@siyavuyachagi/typesharp)
4
+ [![npm version](https://img.shields.io/npm/v/@siyavuyachagi/typesharp.svg?label=Version)](https://www.npmjs.com/package/@siyavuyachagi/typesharp)
5
+ [![npm downloads](https://img.shields.io/npm/dm/@siyavuyachagi/typesharp.svg?label=Downloads)](https://www.npmjs.com/package/@siyavuyachagi/typesharp)
6
+ [![GitHub commits](https://img.shields.io/github/commit-activity/m/siyavuyachagi/typesharp?label=Commits)](https://github.com/siyavuyachagi/typesharp/commits/main)
7
+ [![GitHub last commit](https://img.shields.io/github/last-commit/siyavuyachagi/typesharp?label=Last+commit)](https://github.com/siyavuyachagi/typesharp/commits/main)
8
+ [![GitHub stars](https://img.shields.io/github/stars/siyavuyachagi/typesharp?label=Stars)](https://github.com/siyavuyachagi/typesharp/stargazers)
5
9
  [![Sponsor](https://img.shields.io/badge/Sponsor-πŸ’–-ff69b4)](https://github.com/sponsors/siyavuyachagi)
6
10
 
7
11
  Generate TypeScript types from C# models with ease! TypeSharp scans your ASP.NET Core projects and automatically generates TypeScript interfaces from your C# classes decorated with the `[TypeSharp]` attribute.
8
12
 
13
+ Project structure: [docs/project-structure](docs/project-structure.md)
14
+
9
15
  ## Features
10
16
 
11
- ✨ **Automatic Type Generation** – Convert C# models to TypeScript interfaces
12
- 🎯 **Custom Attribute Targeting** – Use `[TypeSharp]` or any custom attribute
13
- πŸ”„ **Nullable Support** – `string?` β†’ `string | null`
14
- πŸ“¦ **Collection Handling** – Supports `List<T>`, `IEnumerable<T>`, arrays **and generic collections**
15
- πŸ—ΊοΈ **Dictionary Mapping** – `Dictionary<K, V>` β†’ `Record<K, V>`
16
- 🧬 **Generic Types** – Preserves generic type definitions like `Response<T>` β†’ `Response<T>`
17
- 🧬 **Inheritance** – Preserves class inheritance using `extends`
18
- πŸ—οΈ **Computed Properties** – Expression-bodied and block getter properties are included
19
- 🎨 **Naming Conventions** – Convert property names (camel, pascal, snake, kebab)
20
- πŸ“ **Flexible Output** – Single file or multiple files
21
- πŸ”’ **Enum Support** – Converts C# enums to TypeScript string enums
22
- πŸ—‚οΈ **File Grouping** – Preserves C# file organization (multiple classes per file stay together)
23
- πŸ”— **Auto Imports** – Automatically generates `import type` statements between output files
24
- 🏒 **Multi-Project** – Scan multiple `.csproj` files in a single run
17
+ - **Automatic Type Generation** – Convert C# models to TypeScript interfaces
18
+ - **Custom Attribute Targeting** – Use `[TypeSharp]` or any custom attribute
19
+ - **Nullable Support** – `string?` β†’ `string | null`
20
+ - **Collection Handling** – Supports `List<T>`, `IEnumerable<T>`, arrays **and generic collections**
21
+ - **Dictionary Mapping** – `Dictionary<K, V>` β†’ `Record<K, V>`
22
+ - **Generic Types** – Preserves generic type definitions like `Response<T>` β†’ `Response<T>`
23
+ - **Inheritance** – Preserves class inheritance using `extends`
24
+ - **Computed Properties** – Expression-bodied and block getter properties are included
25
+ - **Naming Conventions** – Convert property names (camel, pascal, snake, kebab)
26
+ - **Flexible Output** – Single file or multiple files
27
+ - **Enum Support** – Converts C# enums to TypeScript string enums
28
+ - **File Grouping** – Preserves C# file organization (multiple classes per file stay together)
29
+ - **Auto Imports** – Automatically generates `import type` statements between output files
30
+ - **Multi-Project** – Scan multiple `.csproj` files in a single run
31
+ - **Obsolete Support** – `[Obsolete]` / `[Obsolete("...")]` β†’ `/** @deprecated ... */` JSDoc
25
32
 
26
33
  ## How TypeSharp Compares
27
34
 
28
35
  This is not an OpenApi-based tool !
29
36
  | Feature | TypeSharp | NSwag | openapi-typescript | TypeGen |
30
37
  | --------------------- | --------- | ----- | ------------------ | ------- |
31
- | Direct C# parsing | βœ… | ❌ | ❌ | βœ… |
32
- | Attribute targeting | βœ… | ⚠️ | ❌ | ⚠️ |
33
- | Non-API models | βœ… | ❌ | ❌ | βœ… |
34
- | Generics preserved | βœ… | ⚠️ | ⚠️ | ⚠️ |
35
- | File grouping | βœ… | ❌ | ❌ | ❌ |
36
- | Naming control | βœ… | ⚠️ | ⚠️ | ❌ |
37
- | API client generation | ❌ | βœ… | ❌ | ❌ |
38
+ | Direct C# parsing | βœ“ | βœ• | βœ• | βœ“ |
39
+ | Attribute targeting | βœ“ | ! | βœ• | ! |
40
+ | Non-API models | βœ“ | βœ• | βœ• | βœ“ |
41
+ | Generics preserved | βœ“ | ! | ! | ! |
42
+ | File grouping | βœ“ | βœ• | βœ• | βœ• |
43
+ | Naming control | βœ“ | ! | ! | βœ• |
44
+ | API client generation | βœ• | βœ“ | βœ• | βœ• |
38
45
 
39
- For more [docs/why-typesharp](docs/why-typesharp.md)
46
+ Also see [docs/why-typesharp](docs/why-typesharp.md)
40
47
 
41
48
  ## Installation
42
49
 
@@ -46,20 +53,18 @@ npm install -D @siyavuyachagi/typesharp
46
53
 
47
54
  ## Quick Start
48
55
 
49
- ### 1. Create an attribute to target
56
+ ### 1. Install the NuGet attributes package
50
57
 
51
- In your target project create the following attribute (`TypeSharp`)
58
+ In your C# project:
52
59
 
53
- ```cs
54
- namespace YourProject.Attribute
55
- {
56
- [AttributeUsage(AttributeTargets.Class | AttributeTargets.Enum)]
57
- public class TypeSharpAttribute : Attribute { }
58
- }
60
+ ```bash
61
+ dotnet add package TypeSharp.Attributes
59
62
  ```
60
63
 
61
64
  ### 2. Decorate your C# models or DTOs
62
65
 
66
+ Use `[TypeSharp]` to include a class, or `[TypeSharp("name")]` to include it with a custom TypeScript type name:
67
+
63
68
  ```csharp
64
69
  [TypeSharp]
65
70
  public class User
@@ -114,7 +119,7 @@ This creates `typesharp.config.json`:
114
119
 
115
120
  ```json
116
121
  {
117
- "projectFiles": [
122
+ "source": [
118
123
  "C:/Users/User/Desktop/MyApp/Api/Api.csproj",
119
124
  "C:/Users/User/Desktop/MyApp/Domain/Domain.csproj"
120
125
  ],
@@ -197,7 +202,7 @@ For more advanced usage [docs/usage](docs/usage.md)
197
202
 
198
203
  | Option | Type | Default | Description |
199
204
  | ------------------ | ----------------------------------------- | ------------- | ------------------------------------------------------------- |
200
- | `projectFiles` | `string \| string[]` | _required_ | Full path(s) to your C# .csproj file(s) |
205
+ | `source` | `string \| string[]` | _required_ | Full path(s) to your C# .csproj file(s) |
201
206
  | `outputPath` | `string` | _required_ | Where to generate TypeScript files |
202
207
  | `targetAnnotation` | `string` | `'TypeSharp'` | C# attribute name to look for |
203
208
  | `singleOutputFile` | `boolean` | `false` | Generate one file or multiple files (see below) |
@@ -256,7 +261,7 @@ TypeSharp supports multiple configuration formats:
256
261
 
257
262
  ```json
258
263
  {
259
- "projectFiles": ["C:/Users/User/Desktop/MyApp/Domain/Domain.csproj"],
264
+ "source": ["C:/Users/User/Desktop/MyApp/Domain/Domain.csproj"],
260
265
  "outputPath": "./src/types"
261
266
  }
262
267
  ```
@@ -267,7 +272,7 @@ TypeSharp supports multiple configuration formats:
267
272
  import { TypeSharpConfig } from "typesharp";
268
273
 
269
274
  const config: TypeSharpConfig = {
270
- projectFiles: ["C:/Users/User/Desktop/MyApp/Domain/Domain.csproj"],
275
+ source: ["C:/Users/User/Desktop/MyApp/Domain/Domain.csproj"],
271
276
  outputPath: "./src/types",
272
277
  };
273
278
 
@@ -278,7 +283,7 @@ export default config;
278
283
 
279
284
  ```javascript
280
285
  module.exports = {
281
- projectFiles: ["C:/Users/User/Desktop/MyApp/Domain/Domain.csproj"],
286
+ source: ["C:/Users/User/Desktop/MyApp/Domain/Domain.csproj"],
282
287
  outputPath: "./src/types",
283
288
  };
284
289
  ```
@@ -393,13 +398,83 @@ export interface PermissionMap {
393
398
  }
394
399
  ```
395
400
 
396
- ### 4. Multi-Project
401
+ ### 4. Obsolete / Deprecated Properties
402
+
403
+ **C#:**
404
+
405
+ ```csharp
406
+ [TypeSharp]
407
+ public class Employee
408
+ {
409
+ public int Id { get; set; }
410
+ public string Department { get; set; }
411
+
412
+ [Obsolete("Use Department instead.")]
413
+ public string? DepartmentName { get; set; }
414
+
415
+ [Obsolete]
416
+ public string? LegacyCode { get; set; }
417
+ }
418
+ ```
419
+
420
+ **Generated TypeScript:**
421
+
422
+ ```typescript
423
+ export interface Employee {
424
+ id: number;
425
+ department: string;
426
+ /** @deprecated Use Department instead. */
427
+ departmentName: string | null;
428
+ /** @deprecated */
429
+ legacyCode: string | null;
430
+ }
431
+ ```
432
+
433
+ ### 5. Custom Type Name Override
434
+
435
+ Use `[TypeSharp("name")]` to override the generated TypeScript type name. The override takes precedence over `namingConvention`.
436
+
437
+ **C#:**
438
+
439
+ ```csharp
440
+ [TypeSharp("auth_response")]
441
+ public class AuthResponse
442
+ {
443
+ public string AccessToken { get; set; }
444
+ public string RefreshToken { get; set; }
445
+ }
446
+
447
+ [TypeSharp("user_role")]
448
+ public enum UserRole
449
+ {
450
+ Admin,
451
+ User,
452
+ Guest
453
+ }
454
+ ```
455
+
456
+ **Generated TypeScript:**
457
+
458
+ ```typescript
459
+ export interface auth_response {
460
+ accessToken: string;
461
+ refreshToken: string;
462
+ }
463
+
464
+ export enum user_role {
465
+ Admin = "Admin",
466
+ User = "User",
467
+ Guest = "Guest",
468
+ }
469
+ ```
470
+
471
+ ### 6. Multi-Project
397
472
 
398
473
  Scan multiple C# projects at once:
399
474
 
400
475
  ```json
401
476
  {
402
- "projectFiles": [
477
+ "source": [
403
478
  "C:/MyApp/Api/Api.csproj",
404
479
  "C:/MyApp/Domain/Domain.csproj",
405
480
  "C:/MyApp/Contracts/Contracts.csproj"
@@ -408,13 +483,13 @@ Scan multiple C# projects at once:
408
483
  }
409
484
  ```
410
485
 
411
- ### 5. Single Output File
486
+ ### 7. Single Output File
412
487
 
413
488
  **Config:**
414
489
 
415
490
  ```typescript
416
491
  const config: TypeSharpConfig = {
417
- projectFiles: "./Backend/Backend.csproj",
492
+ source: "./Backend/Backend.csproj",
418
493
  outputPath: "./src/types",
419
494
  singleOutputFile: true,
420
495
  };
@@ -422,13 +497,13 @@ const config: TypeSharpConfig = {
422
497
 
423
498
  All types will be generated in `src/types/types.ts`
424
499
 
425
- ### 6. Custom Naming Conventions
500
+ ### 8. Custom Naming Conventions
426
501
 
427
502
  **Config:**
428
503
 
429
504
  ```typescript
430
505
  const config: TypeSharpConfig = {
431
- projectFiles: "./Backend/Backend.csproj",
506
+ source: "./Backend/Backend.csproj",
432
507
  outputPath: "./src/types",
433
508
  namingConvention: {
434
509
  dir: "kebab", // ./src/types/my-feature/
@@ -480,7 +555,7 @@ generateTypes();
480
555
 
481
556
  ## Requirements
482
557
 
483
- - Node.js >= 14
558
+ - Node.js >= 20
484
559
  - TypeScript >= 4.5 (if using TypeScript config)
485
560
 
486
561
  ## License
package/dist/cli/index.js CHANGED
@@ -7,11 +7,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
7
7
  const commander_1 = require("commander");
8
8
  const core_1 = require("../core");
9
9
  const chalk_1 = __importDefault(require("chalk"));
10
+ const package_json_1 = require("../../package.json");
11
+ const create_sample_config_1 = require("../core/create-sample-config");
10
12
  const program = new commander_1.Command();
11
13
  program
12
- .name('typesharp')
13
- .description('Generate TypeScript types from C# models with TypeSharp attribute')
14
- .version('1.0.0')
14
+ .name(package_json_1.name)
15
+ .description(package_json_1.description)
16
+ .version(package_json_1.version)
15
17
  .usage('[command] [options]');
16
18
  // Generate command (default)
17
19
  program
@@ -39,7 +41,7 @@ program
39
41
  console.error(chalk_1.default.red.bold('❌ Invalid format.') + ' Use: ' + chalk_1.default.yellow('json, ts, ') + 'or' + chalk_1.default.yellow(' js'));
40
42
  process.exit(1);
41
43
  }
42
- (0, core_1.createSampleConfig)(format);
44
+ (0, create_sample_config_1.createSampleConfig)(format);
43
45
  process.exit(0);
44
46
  }
45
47
  catch (error) {
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";;;;;;AAEA,yCAAoC;AACpC,kCAAuD;AACvD,kDAA0B;AAE1B,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,WAAW,CAAC;KACjB,WAAW,CAAC,mEAAmE,CAAC;KAChF,OAAO,CAAC,OAAO,CAAC;KAChB,KAAK,CAAC,qBAAqB,CAAC,CAAC;AAEhC,6BAA6B;AAC7B,OAAO;KACJ,OAAO,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;KACxC,WAAW,CAAC,yCAAyC,CAAC;KACtD,MAAM,CAAC,qBAAqB,EAAE,4BAA4B,CAAC;KAC3D,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;IACxB,IAAI,CAAC;QACH,MAAM,IAAA,eAAQ,EAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC/B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,eAAe;AACf,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,oCAAoC,CAAC;KACjD,MAAM,CAAC,uBAAuB,EAAE,0CAA0C,EAAE,IAAI,CAAC,CAAC,kBAAkB;KACpG,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE;IAClB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,OAAO,CAAC,MAA8B,CAAC;QAEtD,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3C,OAAO,CAAC,KAAK,CAAC,eAAK,CAAC,GAAG,CAAC,IAAI,CAAC,mBAAmB,CAAC,GAAG,QAAQ,GAAG,eAAK,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,IAAI,GAAG,eAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;YACxH,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,IAAA,yBAAkB,EAAC,MAAM,CAAC,CAAC;QAC3B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;YAC3B,OAAO,CAAC,KAAK,CAAC,eAAK,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,eAAK,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;QACxE,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,KAAK,EAAE,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";;;;;;AAEA,yCAAoC;AACpC,kCAAmC;AACnC,kDAA0B;AAC1B,qDAAgE;AAChE,uEAAkE;AAClE,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,mBAAI,CAAC;KACV,WAAW,CAAC,0BAAW,CAAC;KACxB,OAAO,CAAC,sBAAO,CAAC;KAChB,KAAK,CAAC,qBAAqB,CAAC,CAAC;AAEhC,6BAA6B;AAC7B,OAAO;KACJ,OAAO,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;KACxC,WAAW,CAAC,yCAAyC,CAAC;KACtD,MAAM,CAAC,qBAAqB,EAAE,4BAA4B,CAAC;KAC3D,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;IACxB,IAAI,CAAC;QACH,MAAM,IAAA,eAAQ,EAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC/B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,eAAe;AACf,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,oCAAoC,CAAC;KACjD,MAAM,CAAC,uBAAuB,EAAE,0CAA0C,EAAE,IAAI,CAAC,CAAC,kBAAkB;KACpG,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE;IAClB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,OAAO,CAAC,MAA8B,CAAC;QAEtD,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3C,OAAO,CAAC,KAAK,CAAC,eAAK,CAAC,GAAG,CAAC,IAAI,CAAC,mBAAmB,CAAC,GAAG,QAAQ,GAAG,eAAK,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,IAAI,GAAG,eAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;YACxH,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,IAAA,yCAAkB,EAAC,MAAM,CAAC,CAAC;QAC3B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;YAC3B,OAAO,CAAC,KAAK,CAAC,eAAK,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,eAAK,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;QACxE,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,KAAK,EAAE,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Create a sample configuration file
3
+ */
4
+ export declare const createSampleConfig: (format: "ts" | "js" | "json") => void;
5
+ //# sourceMappingURL=create-sample-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-sample-config.d.ts","sourceRoot":"","sources":["../../src/core/create-sample-config.ts"],"names":[],"mappings":"AAKA;;GAEG;AACH,eAAO,MAAM,kBAAkB,GAAI,QAAQ,IAAI,GAAG,IAAI,GAAG,MAAM,KAAG,IA2CjE,CAAA"}
@@ -0,0 +1,110 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.createSampleConfig = void 0;
40
+ const fs = __importStar(require("fs"));
41
+ const chalk_1 = __importDefault(require("chalk"));
42
+ /**
43
+ * Create a sample configuration file
44
+ */
45
+ const createSampleConfig = (format) => {
46
+ const sampleConfig = {
47
+ source: [
48
+ 'C:/Users/User/Desktop/MyApp/MyApp.sln',
49
+ ],
50
+ outputPath: './app/types',
51
+ targetAnnotation: 'TypeSharp',
52
+ singleOutputFile: false,
53
+ namingConvention: 'camel',
54
+ fileSuffix: ''
55
+ };
56
+ let fileName;
57
+ let content;
58
+ if (format === 'json') {
59
+ fileName = 'typesharp.config.json';
60
+ content = JSON.stringify(sampleConfig, null, 2);
61
+ }
62
+ else if (format === 'js') {
63
+ fileName = 'typesharp.config.js';
64
+ content = `module.exports = ${formatAsJsObject(sampleConfig)};\n`;
65
+ }
66
+ else {
67
+ fileName = 'typesharp.config.ts';
68
+ let namespace = '@siyavuyachagi/typesharp';
69
+ content = [
70
+ `import type { TypeSharpConfig } from '${namespace}';`,
71
+ ``,
72
+ `const config: TypeSharpConfig = ${formatAsJsObject(sampleConfig)};`,
73
+ ``,
74
+ `export default config;`,
75
+ ``
76
+ ].join('\n');
77
+ }
78
+ const allConfigFiles = ['typesharp.config.ts', 'typesharp.config.js', 'typesharp.config.json'];
79
+ const existingConfig = allConfigFiles.find(f => fs.existsSync(f));
80
+ if (existingConfig) {
81
+ console.log(chalk_1.default.yellow.bold('❗ Warning:'), chalk_1.default.white(`${existingConfig} already exists. Skipping creation.`));
82
+ return;
83
+ }
84
+ fs.writeFileSync(fileName, content, 'utf-8');
85
+ console.log(chalk_1.default.green.bold('βœ… Created'), chalk_1.default.white(`./${fileName}`));
86
+ };
87
+ exports.createSampleConfig = createSampleConfig;
88
+ /**
89
+ * Format a plain object as a JS/TS object literal (no quoted keys)
90
+ */
91
+ const formatAsJsObject = (obj, indent = 0) => {
92
+ const pad = ' '.repeat(indent + 2);
93
+ const closePad = ' '.repeat(indent);
94
+ const lines = Object.entries(obj).map(([key, value]) => {
95
+ let formatted;
96
+ if (Array.isArray(value)) {
97
+ const items = value.map(v => `${pad} ${JSON.stringify(v)}`).join(',\n');
98
+ formatted = `[\n${items}\n${pad}]`;
99
+ }
100
+ else if (typeof value === 'object' && value !== null) {
101
+ formatted = formatAsJsObject(value, indent + 2);
102
+ }
103
+ else {
104
+ formatted = JSON.stringify(value);
105
+ }
106
+ return `${pad}${key}: ${formatted}`;
107
+ });
108
+ return `{\n${lines.join(',\n')}\n${closePad}}`;
109
+ };
110
+ //# sourceMappingURL=create-sample-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-sample-config.js","sourceRoot":"","sources":["../../src/core/create-sample-config.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,8 @@
1
1
  import { TypeSharpConfig } from '../types/typesharp-config';
2
+ /**
3
+ * Merge user config with defaults
4
+ */
5
+ export declare const mergeWithDefaults: (config: Partial<TypeSharpConfig>) => TypeSharpConfig;
2
6
  export declare function generate(configPath?: string): Promise<void>;
3
7
  /**
4
8
  * Deletes all contents of a directory but keeps the directory itself.
@@ -8,9 +12,5 @@ export declare function cleanOutputDirectory(dir: string): void;
8
12
  /**
9
13
  * Load configuration from file or use provided config
10
14
  */
11
- export declare function loadConfig(configPath?: string): TypeSharpConfig;
12
- /**
13
- * Create a sample configuration file
14
- */
15
- export declare function createSampleConfig(format: 'ts' | 'js' | 'json'): void;
15
+ export declare function loadConfig(configPath?: string): Promise<TypeSharpConfig>;
16
16
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAuD5D,wBAAsB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAiEjE;AASD;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,QAiB/C;AAUD;;GAEG;AACH,wBAAgB,UAAU,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,eAAe,CAqB/D;AA2CD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,IAAI,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAwCrE"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AA6C5D;;GAEG;AACH,eAAO,MAAM,iBAAiB,GAAI,QAAQ,OAAO,CAAC,eAAe,CAAC,KAAG,eAsBpE,CAAC;AAMF,wBAAsB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAiEjE;AASD;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,QAiB/C;AAUD;;GAEG;AACH,wBAAsB,UAAU,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAqB9E"}
@@ -36,63 +36,77 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
36
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
37
37
  };
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.mergeWithDefaults = void 0;
39
40
  exports.generate = generate;
40
41
  exports.cleanOutputDirectory = cleanOutputDirectory;
41
42
  exports.loadConfig = loadConfig;
42
- exports.createSampleConfig = createSampleConfig;
43
43
  const fs = __importStar(require("fs"));
44
44
  const path = __importStar(require("path"));
45
45
  const parser_1 = require("../parser");
46
46
  const generator_1 = require("../generator");
47
47
  const chalk_1 = __importDefault(require("chalk"));
48
+ const url_1 = require("url");
49
+ const resolve_project_files_from_source_1 = require("../parser/resolve-project-files-from-source");
48
50
  /**
49
51
  * Default configuration values
50
52
  */
51
53
  const DEFAULT_CONFIG = {
52
54
  targetAnnotation: 'TypeSharp',
53
55
  singleOutputFile: false,
54
- // fileNamingConvention: 'kebab',
55
56
  namingConvention: 'camel'
56
57
  };
57
58
  /**
58
59
  * Load configuration from a file
59
60
  */
60
- function loadConfigFromFile(filePath) {
61
+ async function loadConfigFromFile(filePath) {
61
62
  const ext = path.extname(filePath);
62
63
  if (ext === '.json') {
63
64
  const content = fs.readFileSync(filePath, 'utf-8');
64
65
  const config = JSON.parse(content);
65
- return mergeWithDefaults(config);
66
- }
67
- if (ext === '.js' || ext === '.ts') {
68
- // For TypeScript/JavaScript files, we need to require them
69
- // eslint-disable-next-line @typescript-eslint/no-var-requires
70
- const config = require(path.resolve(filePath));
71
- const exportedConfig = config.default || config;
72
- return mergeWithDefaults(exportedConfig);
66
+ return (0, exports.mergeWithDefaults)(config);
67
+ }
68
+ if (ext === '.js') {
69
+ const fileUrl = (0, url_1.pathToFileURL)(path.resolve(filePath)).href;
70
+ const module = await Promise.resolve(`${fileUrl}`).then(s => __importStar(require(s)));
71
+ const exportedConfig = module.default || module;
72
+ return (0, exports.mergeWithDefaults)(exportedConfig);
73
+ }
74
+ if (ext === '.ts') {
75
+ // Use tsx to load TypeScript config files at runtime
76
+ const tsxPath = require.resolve('tsx/cjs');
77
+ require(tsxPath);
78
+ const module = require(path.resolve(filePath));
79
+ const exportedConfig = module.default || module;
80
+ return (0, exports.mergeWithDefaults)(exportedConfig);
73
81
  }
74
82
  throw new Error(`Unsupported config file format: ${ext}`);
75
83
  }
76
84
  /**
77
85
  * Merge user config with defaults
78
86
  */
79
- function mergeWithDefaults(config) {
80
- if (!config.projectFiles) {
81
- throw new Error('targetPath is required in configuration');
87
+ const mergeWithDefaults = (config) => {
88
+ // Deprecation warning
89
+ if (config.projectFiles && !config.source) {
90
+ console.warn(chalk_1.default.yellow.bold('⚠ Deprecation:'), chalk_1.default.white('`projectFiles` is deprecated. Please rename it to `source` in your config.'));
91
+ config.source = config.projectFiles;
92
+ }
93
+ if (!config.source && !config.projectFiles) {
94
+ throw new Error('`source` is required in configuration');
82
95
  }
83
96
  if (!config.outputPath) {
84
97
  throw new Error('outputPath is required in configuration');
85
98
  }
86
99
  return {
87
100
  ...DEFAULT_CONFIG,
88
- ...config
101
+ ...config,
89
102
  };
90
- }
103
+ };
104
+ exports.mergeWithDefaults = mergeWithDefaults;
91
105
  async function generate(configPath) {
92
106
  try {
93
107
  console.log(chalk_1.default.cyan.bold('\nπŸš€ TypeSharp - Starting generation...'));
94
108
  // Load configuration
95
- const config = loadConfig(configPath);
109
+ const config = await loadConfig(configPath);
96
110
  console.log(chalk_1.default.green.bold('\nβœ“ Configuration loaded'));
97
111
  // Display project files
98
112
  const projectFiles = Array.isArray(config.projectFiles)
@@ -123,7 +137,7 @@ async function generate(configPath) {
123
137
  console.log(chalk_1.default.cyan('\nβ§– Parsing C# files...'));
124
138
  const parseResults = await (0, parser_1.parseCSharpFiles)(config);
125
139
  if (parseResults.length === 0) {
126
- console.warn(chalk_1.default.yellow.bold('❗ Warning:'), chalk_1.default.white(`No C# files found with [TypeSharp] attribute\n`));
140
+ console.warn(chalk_1.default.yellow.bold('❗ Warning:'), chalk_1.default.white(`No C# files found with [${config.targetAnnotation}] attribute\n`));
127
141
  return;
128
142
  }
129
143
  // Collect all classes
@@ -168,9 +182,9 @@ function cleanOutputDirectory(dir) {
168
182
  /**
169
183
  * Load configuration from file or use provided config
170
184
  */
171
- function loadConfig(configPath) {
185
+ async function loadConfig(configPath) {
172
186
  if (configPath && fs.existsSync(configPath)) {
173
- return loadConfigFromFile(configPath);
187
+ return await loadConfigFromFile(configPath);
174
188
  }
175
189
  // Look for default config files
176
190
  const defaultPaths = [
@@ -180,7 +194,7 @@ function loadConfig(configPath) {
180
194
  ];
181
195
  for (const defaultPath of defaultPaths) {
182
196
  if (fs.existsSync(defaultPath)) {
183
- return loadConfigFromFile(defaultPath);
197
+ return await loadConfigFromFile(defaultPath);
184
198
  }
185
199
  }
186
200
  throw new Error('No configuration file found. Please create typesharp.config.ts, typesharp.config.js, or typesharp.config.json');
@@ -190,9 +204,7 @@ function loadConfig(configPath) {
190
204
  */
191
205
  function validateConfig(config) {
192
206
  // Convert single project to array for unified handling
193
- const projectFiles = Array.isArray(config.projectFiles)
194
- ? config.projectFiles
195
- : [config.projectFiles];
207
+ const projectFiles = (0, resolve_project_files_from_source_1.resolveProjectFilesFromSource)(config.source);
196
208
  // Validate each project file
197
209
  for (const projectFile of projectFiles) {
198
210
  if (!fs.existsSync(projectFile)) {
@@ -218,46 +230,4 @@ function validateConfig(config) {
218
230
  }
219
231
  }
220
232
  }
221
- /**
222
- * Create a sample configuration file
223
- */
224
- function createSampleConfig(format) {
225
- const sampleConfig = {
226
- // Show array format as example
227
- projectFiles: [
228
- 'C:/Users/User/Desktop/MyApp/Api/Api.csproj',
229
- 'C:/Users/User/Desktop/MyApp/Domain/Domain.csproj'
230
- ],
231
- outputPath: './app/types',
232
- targetAnnotation: 'TypeSharp',
233
- singleOutputFile: false,
234
- namingConvention: 'camel',
235
- fileSuffix: ''
236
- };
237
- let fileName;
238
- let content;
239
- if (format === 'json') {
240
- fileName = 'typesharp.config.json';
241
- content = JSON.stringify(sampleConfig, null, 2);
242
- }
243
- else if (format === 'js') {
244
- fileName = 'typesharp.config.js';
245
- content = `module.exports = ${JSON.stringify(sampleConfig, null, 2)};\n`;
246
- }
247
- else {
248
- fileName = 'typesharp.config.ts';
249
- content = `import type { TypeSharpConfig } from 'typesharp';
250
-
251
- const config: TypeSharpConfig = ${JSON.stringify(sampleConfig, null, 2)};
252
-
253
- export default config;
254
- `;
255
- }
256
- if (fs.existsSync(fileName)) {
257
- console.log(chalk_1.default.yellow.bold('❗ Warning:'), chalk_1.default.white(`${fileName} already exists. Skipping creation.`));
258
- return;
259
- }
260
- fs.writeFileSync(fileName, content, 'utf-8');
261
- console.log(chalk_1.default.green.bold('βœ… Created'), chalk_1.default.white(`./${fileName}`));
262
- }
263
233
  //# sourceMappingURL=index.js.map