@macroforge/mcp-server 0.1.33 → 0.1.35

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 (50) hide show
  1. package/README.md +68 -0
  2. package/dist/index.d.ts +32 -0
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +46 -1
  5. package/dist/index.js.map +1 -1
  6. package/dist/tools/docs-loader.d.ts +133 -5
  7. package/dist/tools/docs-loader.d.ts.map +1 -1
  8. package/dist/tools/docs-loader.js +131 -15
  9. package/dist/tools/docs-loader.js.map +1 -1
  10. package/dist/tools/index.d.ts +48 -1
  11. package/dist/tools/index.d.ts.map +1 -1
  12. package/dist/tools/index.js +163 -14
  13. package/dist/tools/index.js.map +1 -1
  14. package/docs/api/api-overview.md +24 -46
  15. package/docs/api/expand-sync.md +24 -51
  16. package/docs/api/native-plugin.md +24 -56
  17. package/docs/api/position-mapper.md +34 -76
  18. package/docs/api/transform-sync.md +27 -59
  19. package/docs/builtin-macros/clone.md +45 -104
  20. package/docs/builtin-macros/debug.md +33 -104
  21. package/docs/builtin-macros/default.md +78 -114
  22. package/docs/builtin-macros/deserialize.md +93 -273
  23. package/docs/builtin-macros/hash.md +58 -100
  24. package/docs/builtin-macros/macros-overview.md +42 -103
  25. package/docs/builtin-macros/ord.md +65 -133
  26. package/docs/builtin-macros/partial-eq.md +53 -179
  27. package/docs/builtin-macros/partial-ord.md +67 -159
  28. package/docs/builtin-macros/serialize.md +64 -194
  29. package/docs/concepts/architecture.md +40 -99
  30. package/docs/concepts/derive-system.md +129 -125
  31. package/docs/concepts/how-macros-work.md +52 -84
  32. package/docs/custom-macros/custom-overview.md +17 -39
  33. package/docs/custom-macros/rust-setup.md +22 -55
  34. package/docs/custom-macros/ts-macro-derive.md +43 -107
  35. package/docs/custom-macros/ts-quote.md +177 -507
  36. package/docs/getting-started/first-macro.md +108 -33
  37. package/docs/getting-started/installation.md +32 -73
  38. package/docs/integration/cli.md +70 -156
  39. package/docs/integration/configuration.md +32 -75
  40. package/docs/integration/integration-overview.md +16 -55
  41. package/docs/integration/mcp-server.md +30 -69
  42. package/docs/integration/svelte-preprocessor.md +60 -83
  43. package/docs/integration/typescript-plugin.md +32 -74
  44. package/docs/integration/vite-plugin.md +30 -79
  45. package/docs/language-servers/ls-overview.md +22 -46
  46. package/docs/language-servers/svelte.md +30 -69
  47. package/docs/language-servers/zed.md +34 -72
  48. package/docs/roadmap/roadmap.md +54 -130
  49. package/docs/sections.json +3 -262
  50. package/package.json +2 -2
@@ -1,123 +1,81 @@
1
1
  # Hash
2
2
 
3
- *The `Hash` macro generates a `hashCode()` method that computes a numeric hash value based on field values.*
3
+ The `Hash` macro generates a `hashCode()` method for computing numeric hash codes.
4
+ This is analogous to Rust's `Hash` trait and Java's `hashCode()` method, enabling
5
+ objects to be used as keys in hash-based collections.
4
6
 
5
- ## Basic Usage
7
+ ## Generated Output
6
8
 
7
- <MacroExample before={data.examples.basic.before} after={data.examples.basic.after} />
9
+ | Type | Generated Code | Description |
10
+ |------|----------------|-------------|
11
+ | Class | `hashCode(): number` | Instance method computing hash from all fields |
12
+ | Enum | `hashCodeEnumName(value: EnumName): number` | Standalone function hashing by enum value |
13
+ | Interface | `hashCodeInterfaceName(value: InterfaceName): number` | Standalone function computing hash |
14
+ | Type Alias | `hashCodeTypeName(value: TypeName): number` | Standalone function computing hash |
8
15
 
9
- ```typescript
10
- const p1 = new Point(10, 20);
11
- const p2 = new Point(10, 20);
12
- const p3 = new Point(5, 5);
16
+ ## Configuration
13
17
 
14
- console.log(p1.hashCode()); // Same hash
15
- console.log(p2.hashCode()); // Same hash (equal values = equal hash)
16
- console.log(p3.hashCode()); // Different hash
17
- ```
18
+ The `functionNamingStyle` option in `macroforge.json` controls naming:
19
+ - `"suffix"` (default): Suffixes with type name (e.g., `hashCodeMyType`)
20
+ - `"prefix"`: Prefixes with type name (e.g., `myTypeHashCode`)
21
+ - `"generic"`: Uses TypeScript generics (e.g., `hashCode<T extends MyType>`)
22
+ - `"namespace"`: Legacy namespace wrapping
18
23
 
19
24
  ## Hash Algorithm
20
25
 
21
- The generated hash function uses the following algorithm for different types:
22
-
23
- - `number` → Integers use bitwise OR (`| 0`), floats are stringified and hashed
24
-
25
- - `string` → Character-by-character hash: `(h * 31 + charCode) | 0`
26
-
27
- - `boolean` → `1231` for true, `1237` for false (Java convention)
28
-
29
- - `bigint` → Converted to string and hashed character-by-character
30
-
31
- - `Date` → Uses `getTime() | 0` for timestamp hash
32
-
33
- - `Array` → Combines element hashes with `h * 31 + elementHash`
34
-
35
- - `Map/Set` → Combines all entry hashes
36
-
37
- - `Object` → Calls `hashCode()` if available, otherwise JSON stringifies and hashes
38
-
39
- - `null` → Returns 0
40
-
41
- - `undefined` → Returns 1
42
-
43
- ## Field Options
44
-
45
- ### @hash(skip)
46
-
47
- Use `@hash(skip)` to exclude a field from hash computation:
48
-
49
- <MacroExample before={data.examples.skip.before} after={data.examples.skip.after} />
50
-
51
- ```typescript
52
- const user1 = new User(1, "Alice", new Date("2024-01-01"));
53
- const user2 = new User(1, "Alice", new Date("2024-12-01"));
54
-
55
- console.log(user1.hashCode() === user2.hashCode()); // true (lastLogin is skipped)
56
- ```
57
-
58
- ## Use with PartialEq
59
-
60
- Hash is often used together with PartialEq. Objects that are equal should have the same hash code:
61
-
62
- <InteractiveMacro code={`/** @derive(Hash, PartialEq) */
63
- class Product {
64
- sku: string;
65
- name: string;
66
-
67
- constructor(sku: string, name: string) {
68
- this.sku = sku;
69
- this.name = name;
70
- }
71
- }`} />
72
-
73
- ```typescript
74
- const p1 = new Product("ABC123", "Widget");
75
- const p2 = new Product("ABC123", "Widget");
76
-
77
- // Equal objects have equal hash codes
78
- console.log(p1.equals(p2)); // true
79
- console.log(p1.hashCode() === p2.hashCode()); // true
80
- ```
81
-
82
- ## Interface Support
83
-
84
- Hash also works with interfaces. For interfaces, a namespace is generated with a `hashCode` function:
26
+ Uses the standard polynomial rolling hash algorithm:
85
27
 
86
- <MacroExample before={data.examples.interface.before} after={data.examples.interface.after} />
87
-
88
- ```typescript
89
- const p: Point = { x: 10, y: 20 };
90
- console.log(Point.hashCode(p)); // numeric hash value
28
+ ```text
29
+ hash = 17 // Initial seed
30
+ for each field:
31
+ hash = (hash * 31 + fieldHash) | 0 // Bitwise OR keeps it 32-bit integer
91
32
  ```
92
33
 
93
- ## Enum Support
34
+ This algorithm is consistent with Java's `Objects.hash()` implementation.
94
35
 
95
- Hash works with enums. For string enums, it hashes the string value; for numeric enums, it uses the numeric value directly:
36
+ ## Type-Specific Hashing
96
37
 
97
- <MacroExample before={data.examples.enum.before} after={data.examples.enum.after} />
38
+ | Type | Hash Strategy |
39
+ |------|---------------|
40
+ | `number` | Integer: direct value; Float: string hash of decimal |
41
+ | `bigint` | String hash of decimal representation |
42
+ | `string` | Character-by-character polynomial hash |
43
+ | `boolean` | 1231 for true, 1237 for false (Java convention) |
44
+ | `Date` | `getTime()` timestamp |
45
+ | Arrays | Element-by-element hash combination |
46
+ | `Map` | Entry-by-entry key+value hash |
47
+ | `Set` | Element-by-element hash |
48
+ | Objects | Calls `hashCode()` if available, else JSON string hash |
98
49
 
99
- ```typescript
100
- console.log(Status.hashCode(Status.Active)); // consistent hash
101
- console.log(Status.hashCode(Status.Inactive)); // different hash
102
- ```
50
+ ## Field-Level Options
103
51
 
104
- ## Type Alias Support
52
+ The `@hash` decorator supports:
105
53
 
106
- Hash works with type aliases. For object types, it hashes each field:
54
+ - `skip` - Exclude the field from hash calculation
107
55
 
108
- <MacroExample before={data.examples.typeAlias.before} after={data.examples.typeAlias.after} />
56
+ ## Example
109
57
 
110
58
  ```typescript
111
- const loc: Coordinates = { lat: 40.7128, lng: -74.0060 };
112
- console.log(Coordinates.hashCode(loc));
59
+ @derive(Hash, PartialEq)
60
+ class User {
61
+ id: number;
62
+ name: string;
63
+
64
+ @hash(skip) // Cached value shouldn't affect hash
65
+ cachedScore: number;
66
+ }
67
+
68
+ // Generated:
69
+ // hashCode(): number {
70
+ // let hash = 17;
71
+ // hash = (hash * 31 + (Number.isInteger(this.id) ? this.id | 0 : ...)) | 0;
72
+ // hash = (hash * 31 + (this.name ?? '').split('').reduce(...)) | 0;
73
+ // return hash;
74
+ // }
113
75
  ```
114
76
 
115
- For union types, it uses JSON stringification as a fallback:
77
+ ## Hash Contract
116
78
 
117
- <InteractiveMacro code={`/** @derive(Hash) */
118
- type Result = "success" | "error" | "pending";`} />
119
-
120
- ```typescript
121
- console.log(Result.hashCode("success")); // hash of "success" string
122
- console.log(Result.hashCode("error")); // hash of "error" string
123
- ```
79
+ Objects that are equal (`PartialEq`) should produce the same hash code.
80
+ When using `@hash(skip)`, ensure the same fields are skipped in both
81
+ `Hash` and `PartialEq` to maintain this contract.
@@ -1,50 +1,20 @@
1
1
  # Built-in Macros
2
-
3
- *Macroforge comes with built-in derive macros that cover the most common code generation needs. All macros work with classes, interfaces, enums, and type aliases.*
4
-
5
- ## Overview
6
-
7
- | [`Debug`]({base}/docs/builtin-macros/debug)
8
- | `toString(): string`
9
- | Human-readable string representation
10
-
11
- | [`Clone`]({base}/docs/builtin-macros/clone)
12
- | `clone(): T`
13
- | Creates a deep copy of the object
14
-
15
- | [`Default`]({base}/docs/builtin-macros/default)
16
- | `static default(): T`
17
- | Creates an instance with default values
18
-
19
- | [`Hash`]({base}/docs/builtin-macros/hash)
20
- | `hashCode(): number`
21
- | Generates a hash code for the object
22
-
23
- | [`PartialEq`]({base}/docs/builtin-macros/partial-eq)
24
- | `equals(other: T): boolean`
25
- | Value equality comparison
26
-
27
- | [`Ord`]({base}/docs/builtin-macros/ord)
28
- | `compare(other: T): number`
29
- | Total ordering comparison (-1, 0, 1)
30
-
31
- | [`PartialOrd`]({base}/docs/builtin-macros/partial-ord)
32
- | `partialCompare(other: T): number | null`
33
- | Partial ordering comparison
34
-
35
- | [`Serialize`]({base}/docs/builtin-macros/serialize)
36
- | `toJSON(): Record<string, unknown>`
37
- | JSON serialization with type handling
38
-
39
- | [`Deserialize`]({base}/docs/builtin-macros/deserialize)
40
- | `static fromJSON(data: unknown): T`
41
- | JSON deserialization with validation
42
-
43
- ## Using Built-in Macros
44
-
45
- Built-in macros don't require imports. Just use them with `@derive`:
46
-
47
- ```typescript
2
+ *Macroforge comes with built-in derive macros that cover the most common code generation needs. All macros work with classes, interfaces, enums, and type aliases.*
3
+ ## Overview
4
+ | Macro | Generates | Description |
5
+ | --- | --- | --- |
6
+ | [`Debug`](../docs/builtin-macros/debug) | `toString(): string` | Human-readable string representation |
7
+ | [`Clone`](../docs/builtin-macros/clone) | `clone(): T` | Creates a deep copy of the object |
8
+ | [`Default`](../docs/builtin-macros/default) | `static default(): T` | Creates an instance with default values |
9
+ | [`Hash`](../docs/builtin-macros/hash) | `hashCode(): number` | Generates a hash code for the object |
10
+ | [`PartialEq`](../docs/builtin-macros/partial-eq) | `equals(other: T): boolean` | Value equality comparison |
11
+ | [`Ord`](../docs/builtin-macros/ord) | `compare(other: T): number` | Total ordering comparison (-1, 0, 1) |
12
+ | [`PartialOrd`](../docs/builtin-macros/partial-ord) | `partialCompare(other: T): number | null` | Partial ordering comparison |
13
+ | [`Serialize`](../docs/builtin-macros/serialize) | `toJSON(): Record<string, unknown>` | JSON serialization with type handling |
14
+ | [`Deserialize`](../docs/builtin-macros/deserialize) | `static fromJSON(data: unknown): T` | JSON deserialization with validation |
15
+ ## Using Built-in Macros
16
+ Built-in macros don't require imports. Just use them with `@derive`:
17
+ ```
48
18
  /** @derive(Debug, Clone, PartialEq) */
49
19
  class User {
50
20
  name: string;
@@ -55,13 +25,9 @@ class User {
55
25
  this.age = age;
56
26
  }
57
27
  }
58
- ```
59
-
60
- ## Interface Support
61
-
62
- All built-in macros work with interfaces. For interfaces, methods are generated as functions in a namespace with the same name, using `self` as the first parameter:
63
-
64
- ```typescript
28
+ ``` ## Interface Support
29
+ All built-in macros work with interfaces. For interfaces, methods are generated as functions in a namespace with the same name, using `self` as the first parameter:
30
+ ```
65
31
  /** @derive(Debug, Clone, PartialEq) */
66
32
  interface Point {
67
33
  x: number;
@@ -82,13 +48,9 @@ const point: Point = { x: 10, y: 20 };
82
48
  console.log(Point.toString(point)); // "Point { x: 10, y: 20 }"
83
49
  const copy = Point.clone(point); // { x: 10, y: 20 }
84
50
  console.log(Point.equals(point, copy)); // true
85
- ```
86
-
87
- ## Enum Support
88
-
89
- All built-in macros work with enums. For enums, methods are generated as functions in a namespace with the same name:
90
-
91
- ```typescript
51
+ ``` ## Enum Support
52
+ All built-in macros work with enums. For enums, methods are generated as functions in a namespace with the same name:
53
+ ```
92
54
  /** @derive(Debug, Clone, PartialEq, Serialize, Deserialize) */
93
55
  enum Status {
94
56
  Active = "active",
@@ -111,13 +73,9 @@ console.log(Status.toString(Status.Active)); // "Status.Active"
111
73
  console.log(Status.equals(Status.Active, Status.Active)); // true
112
74
  const json = Status.toJSON(Status.Pending); // "pending"
113
75
  const parsed = Status.fromJSON("active"); // Status.Active
114
- ```
115
-
116
- ## Type Alias Support
117
-
118
- All built-in macros work with type aliases. For object type aliases, field-aware methods are generated in a namespace:
119
-
120
- ```typescript
76
+ ``` ## Type Alias Support
77
+ All built-in macros work with type aliases. For object type aliases, field-aware methods are generated in a namespace:
78
+ ```
121
79
  /** @derive(Debug, Clone, PartialEq, Serialize, Deserialize) */
122
80
  type Point = {
123
81
  x: number;
@@ -138,24 +96,17 @@ const point: Point = { x: 10, y: 20 };
138
96
  console.log(Point.toString(point)); // "Point { x: 10, y: 20 }"
139
97
  const copy = Point.clone(point); // { x: 10, y: 20 }
140
98
  console.log(Point.equals(point, copy)); // true
141
- ```
142
-
143
- Union type aliases also work, using JSON-based implementations:
144
-
145
- ```typescript
99
+ ``` Union type aliases also work, using JSON-based implementations:
100
+ ```
146
101
  /** @derive(Debug, PartialEq) */
147
102
  type ApiStatus = "loading" | "success" | "error";
148
103
 
149
104
  const status: ApiStatus = "success";
150
- console.log(ApiStatus.toString(status)); // "ApiStatus(\\"success\\")"
105
+ console.log(ApiStatus.toString(status)); // "ApiStatus(\"success\")"
151
106
  console.log(ApiStatus.equals("success", "success")); // true
152
- ```
153
-
154
- ## Combining Macros
155
-
156
- All macros can be used together. They don't conflict and each generates independent methods:
157
-
158
- ```typescript
107
+ ``` ## Combining Macros
108
+ All macros can be used together. They don't conflict and each generates independent methods:
109
+ ```
159
110
  const user = new User("Alice", 30);
160
111
 
161
112
  // Debug
@@ -168,26 +119,14 @@ console.log(copy.name); // "Alice"
168
119
 
169
120
  // Eq
170
121
  console.log(user.equals(copy)); // true
171
- ```
172
-
173
- ## Detailed Documentation
174
-
175
- Each macro has its own options and behaviors:
176
-
177
- - [**Debug**]({base}/docs/builtin-macros/debug) - Customizable field renaming and skipping
178
-
179
- - [**Clone**]({base}/docs/builtin-macros/clone) - Deep copying for all field types
180
-
181
- - [**Default**]({base}/docs/builtin-macros/default) - Default value generation with field attributes
182
-
183
- - [**Hash**]({base}/docs/builtin-macros/hash) - Hash code generation for use in maps and sets
184
-
185
- - [**PartialEq**]({base}/docs/builtin-macros/partial-eq) - Value-based equality comparison
186
-
187
- - [**Ord**]({base}/docs/builtin-macros/ord) - Total ordering for sorting
188
-
189
- - [**PartialOrd**]({base}/docs/builtin-macros/partial-ord) - Partial ordering comparison
190
-
191
- - [**Serialize**]({base}/docs/builtin-macros/serialize) - JSON serialization with serde-style options
192
-
193
- - [**Deserialize**]({base}/docs/builtin-macros/deserialize) - JSON deserialization with validation
122
+ ``` ## Detailed Documentation
123
+ Each macro has its own options and behaviors:
124
+ - [**Debug**](../docs/builtin-macros/debug) - Customizable field renaming and skipping
125
+ - [**Clone**](../docs/builtin-macros/clone) - Deep copying for all field types
126
+ - [**Default**](../docs/builtin-macros/default) - Default value generation with field attributes
127
+ - [**Hash**](../docs/builtin-macros/hash) - Hash code generation for use in maps and sets
128
+ - [**PartialEq**](../docs/builtin-macros/partial-eq) - Value-based equality comparison
129
+ - [**Ord**](../docs/builtin-macros/ord) - Total ordering for sorting
130
+ - [**PartialOrd**](../docs/builtin-macros/partial-ord) - Partial ordering comparison
131
+ - [**Serialize**](../docs/builtin-macros/serialize) - JSON serialization with serde-style options
132
+ - [**Deserialize**](../docs/builtin-macros/deserialize) - JSON deserialization with validation
@@ -1,159 +1,91 @@
1
1
  # Ord
2
2
 
3
- *The `Ord` macro generates a `compareTo()` method that implements total ordering, always returning `-1`, `0`, or `1`.*
3
+ The `Ord` macro generates a `compareTo()` method for **total ordering** comparison.
4
+ This is analogous to Rust's `Ord` trait, enabling objects to be sorted and
5
+ compared with a guaranteed ordering relationship.
4
6
 
5
- ## Basic Usage
7
+ ## Generated Output
6
8
 
7
- <MacroExample before={data.examples.basic.before} after={data.examples.basic.after} />
9
+ | Type | Generated Code | Description |
10
+ |------|----------------|-------------|
11
+ | Class | `compareTo(other): number` | Instance method returning -1, 0, or 1 |
12
+ | Enum | `compareEnumName(a: EnumName, b: EnumName): number` | Standalone function comparing enum values |
13
+ | Interface | `compareInterfaceName(a: InterfaceName, b: InterfaceName): number` | Standalone function comparing fields |
14
+ | Type Alias | `compareTypeName(a: TypeName, b: TypeName): number` | Standalone function with type-appropriate comparison |
8
15
 
9
- ```typescript
10
- const v1 = new Version(1, 0, 0);
11
- const v2 = new Version(1, 2, 0);
12
- const v3 = new Version(1, 2, 0);
13
-
14
- console.log(v1.compareTo(v2)); // -1 (v1 < v2)
15
- console.log(v2.compareTo(v1)); // 1 (v2 > v1)
16
- console.log(v2.compareTo(v3)); // 0 (v2 == v3)
17
- ```
18
-
19
- ## Comparison Logic
20
-
21
- The Ord macro compares fields in declaration order (lexicographic ordering). For each type:
22
-
23
- - `number` / `bigint` → Direct numeric comparison
24
-
25
- - `string` → Uses `localeCompare()` clamped to -1/0/1
26
-
27
- - `boolean` → `false < true`
28
-
29
- - `Date` → Compares timestamps via `getTime()`
30
-
31
- - `Array` → Lexicographic: compares element-by-element, then length
32
-
33
- - `Map/Set` → Size and content comparison
16
+ ## Configuration
34
17
 
35
- - `Object` Calls `compareTo()` if available, otherwise 0
36
-
37
- - `null/undefined` Treated as equal (returns 0)
18
+ The `functionNamingStyle` option in `macroforge.json` controls naming:
19
+ - `"suffix"` (default): Suffixes with type name (e.g., `compareMyType`)
20
+ - `"prefix"`: Prefixes with type name (e.g., `myTypeCompare`)
21
+ - `"generic"`: Uses TypeScript generics (e.g., `compare<T extends MyType>`)
22
+ - `"namespace"`: Legacy namespace wrapping
38
23
 
39
24
  ## Return Values
40
25
 
41
- The `compareTo()` method always returns:
42
-
43
- - `-1` → `this` is less than `other`
44
-
45
- - `0` → `this` equals `other`
26
+ Unlike `PartialOrd`, `Ord` provides **total ordering** - every pair of values
27
+ can be compared:
46
28
 
47
- - `1` `this` is greater than `other`
29
+ - **-1**: `this` is less than `other`
30
+ - **0**: `this` is equal to `other`
31
+ - **1**: `this` is greater than `other`
48
32
 
49
- Unlike `PartialOrd`, the `Ord` macro never returns `null` - it provides total ordering.
33
+ The method **never returns null** - all values must be comparable.
50
34
 
51
- ## Field Options
35
+ ## Comparison Strategy
52
36
 
53
- ### @ord(skip)
37
+ Fields are compared **lexicographically** in declaration order:
54
38
 
55
- Use `@ord(skip)` to exclude a field from ordering comparison:
39
+ 1. Compare first field
40
+ 2. If not equal, return that result
41
+ 3. Otherwise, compare next field
42
+ 4. Continue until a difference is found or all fields are equal
56
43
 
57
- <MacroExample before={data.examples.skip.before} after={data.examples.skip.after} />
58
-
59
- ```typescript
60
- const t1 = new Task(1, "Bug fix", new Date("2024-01-01"));
61
- const t2 = new Task(1, "Bug fix", new Date("2024-12-01"));
44
+ ## Type-Specific Comparisons
62
45
 
63
- console.log(t1.compareTo(t2)); // 0 (createdAt is skipped)
64
- ```
46
+ | Type | Comparison Method |
47
+ |------|-------------------|
48
+ | `number`/`bigint` | Direct `<` and `>` comparison |
49
+ | `string` | `localeCompare()` (clamped to -1, 0, 1) |
50
+ | `boolean` | false &lt; true |
51
+ | Arrays | Lexicographic element-by-element |
52
+ | `Date` | `getTime()` timestamp comparison |
53
+ | Objects | Calls `compareTo()` if available, else 0 |
65
54
 
66
- ## Sorting Arrays
55
+ ## Field-Level Options
67
56
 
68
- The generated `compareTo()` method works directly with `Array.sort()`:
57
+ The `@ord` decorator supports:
69
58
 
70
- <InteractiveMacro code={`/** @derive(Ord) */
71
- class Score {
72
- points: number;
73
- name: string;
59
+ - `skip` - Exclude the field from ordering comparison
74
60
 
75
- constructor(points: number, name: string) {
76
- this.points = points;
77
- this.name = name;
78
- }
79
- }`} />
61
+ ## Example
80
62
 
81
63
  ```typescript
82
- const scores = [
83
- new Score(100, "Alice"),
84
- new Score(50, "Bob"),
85
- new Score(150, "Charlie"),
86
- new Score(50, "Alice") // Same points, different name
87
- ];
88
-
89
- // Sort ascending
90
- scores.sort((a, b) => a.compareTo(b));
91
- // Result: [Bob(50), Alice(50), Alice(100), Charlie(150)]
92
-
93
- // Sort descending
94
- scores.sort((a, b) => b.compareTo(a));
95
- // Result: [Charlie(150), Alice(100), Alice(50), Bob(50)]
96
- ```
97
-
98
- ## Interface Support
99
-
100
- Ord works with interfaces. For interfaces, a namespace is generated with a `compareTo` function:
101
-
102
- <MacroExample before={data.examples.interface.before} after={data.examples.interface.after} />
103
-
104
- ```typescript
105
- const points: Point[] = [
106
- { x: 5, y: 10 },
107
- { x: 1, y: 20 },
108
- { x: 5, y: 5 }
109
- ];
110
-
111
- points.sort((a, b) => Point.compareTo(a, b));
112
- // Result: [{ x: 1, y: 20 }, { x: 5, y: 5 }, { x: 5, y: 10 }]
113
- ```
114
-
115
- ## Enum Support
116
-
117
- Ord works with enums. For numeric enums, it compares the numeric values; for string enums, it uses string comparison:
118
-
119
- <MacroExample before={data.examples.enum.before} after={data.examples.enum.after} />
120
-
121
- ```typescript
122
- console.log(Priority.compareTo(Priority.Low, Priority.High)); // -1
123
- console.log(Priority.compareTo(Priority.Critical, Priority.Low)); // 1
124
- console.log(Priority.compareTo(Priority.Medium, Priority.Medium)); // 0
125
- ```
126
-
127
- ## Type Alias Support
128
-
129
- Ord works with type aliases. For object types, it uses lexicographic field comparison:
130
-
131
- <MacroExample before={data.examples.typeAlias.before} after={data.examples.typeAlias.after} />
132
-
133
- ```typescript
134
- const c1: Coordinate = { x: 10, y: 20 };
135
- const c2: Coordinate = { x: 10, y: 30 };
136
-
137
- console.log(Coordinate.compareTo(c1, c2)); // -1 (c1 < c2)
64
+ @derive(Ord)
65
+ class Version {
66
+ major: number;
67
+ minor: number;
68
+ patch: number;
69
+ }
70
+
71
+ // Generated:
72
+ // compareTo(other: Version): number {
73
+ // if (this === other) return 0;
74
+ // const typedOther = other;
75
+ // const cmp0 = this.major < typedOther.major ? -1 : this.major > typedOther.major ? 1 : 0;
76
+ // if (cmp0 !== 0) return cmp0;
77
+ // const cmp1 = this.minor < typedOther.minor ? -1 : ...;
78
+ // if (cmp1 !== 0) return cmp1;
79
+ // const cmp2 = this.patch < typedOther.patch ? -1 : ...;
80
+ // if (cmp2 !== 0) return cmp2;
81
+ // return 0;
82
+ // }
83
+
84
+ // Usage:
85
+ versions.sort((a, b) => a.compareTo(b));
138
86
  ```
139
87
 
140
88
  ## Ord vs PartialOrd
141
89
 
142
- Use `Ord` when all values of a type are comparable. Use `PartialOrd` when some values might be incomparable (e.g., different types at runtime).
143
-
144
- <InteractiveMacro code={`// Ord: Total ordering - never returns null
145
- /** @derive(Ord) */
146
- class Version {
147
- major: number;
148
- minor: number;
149
- constructor(major: number, minor: number) {
150
- this.major = major;
151
- this.minor = minor;
152
- }
153
- }`} />
154
-
155
- ```typescript
156
- const v1 = new Version(1, 0);
157
- const v2 = new Version(2, 0);
158
- console.log(v1.compareTo(v2)); // Always -1, 0, or 1
159
- ```
90
+ - Use **Ord** when all values are comparable (total ordering)
91
+ - Use **PartialOrd** when some values may be incomparable (returns `Option<number>`)