@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,10 +1,7 @@
1
1
  # PositionMapper
2
-
3
- *Maps positions between original source code and macro-expanded code. Essential for accurate error reporting and debugging.*
4
-
5
- ## Getting a Mapper
6
-
7
- ```typescript
2
+ *Bidirectional position mapper for translating between original and expanded source positions. This mapper enables IDE features like error reporting, go-to-definition, and hover to work correctly with macro-expanded code by translating positions between the original source (what the user wrote) and the expanded source (what the compiler sees).*
3
+ ## Getting a Mapper
4
+ ```
8
5
  import { NativePlugin, PositionMapper } from "macroforge";
9
6
 
10
7
  const plugin = new NativePlugin();
@@ -15,76 +12,43 @@ const mapper = plugin.getMapper("user.ts");
15
12
  if (mapper) {
16
13
  // Use the mapper...
17
14
  }
18
- ```
19
-
20
- ## Methods
21
-
22
- ### isEmpty()
23
-
24
- Check if the mapper has any mappings:
25
-
26
- ```typescript
15
+ ``` ## Methods
16
+ ### isEmpty()
17
+ Check if the mapper has any mappings:
18
+ ```
27
19
  isEmpty(): boolean
28
- ```
29
-
30
- ### originalToExpanded()
31
-
32
- Map a position from original to expanded code:
33
-
34
- ```typescript
20
+ ``` ### originalToExpanded()
21
+ Map a position from original to expanded code:
22
+ ```
35
23
  originalToExpanded(pos: number): number
36
- ```
37
-
38
- ### expandedToOriginal()
39
-
40
- Map a position from expanded to original code:
41
-
42
- ```typescript
24
+ ``` ### expandedToOriginal()
25
+ Map a position from expanded to original code:
26
+ ```
43
27
  expandedToOriginal(pos: number): number | null
44
- ```
45
-
46
- Returns `null` if the position is in generated code.
47
-
48
- ### isInGenerated()
49
-
50
- Check if a position is in macro-generated code:
51
-
52
- ```typescript
28
+ ``` Returns `null` if the position is in generated code.
29
+ ### isInGenerated()
30
+ Check if a position is in macro-generated code:
31
+ ```
53
32
  isInGenerated(pos: number): boolean
54
- ```
55
-
56
- ### generatedBy()
57
-
58
- Get the name of the macro that generated code at a position:
59
-
60
- ```typescript
33
+ ``` ### generatedBy()
34
+ Get the name of the macro that generated code at a position:
35
+ ```
61
36
  generatedBy(pos: number): string | null
62
- ```
63
-
64
- ### mapSpanToOriginal()
65
-
66
- Map a span (range) from expanded to original code:
67
-
68
- ```typescript
37
+ ``` ### mapSpanToOriginal()
38
+ Map a span (range) from expanded to original code:
39
+ ```
69
40
  mapSpanToOriginal(start: number, length: number): SpanResult | null
70
41
 
71
42
  interface SpanResult {
72
43
  start: number;
73
44
  length: number;
74
45
  }
75
- ```
76
-
77
- ### mapSpanToExpanded()
78
-
79
- Map a span from original to expanded code:
80
-
81
- ```typescript
46
+ ``` ### mapSpanToExpanded()
47
+ Map a span from original to expanded code:
48
+ ```
82
49
  mapSpanToExpanded(start: number, length: number): SpanResult
83
- ```
84
-
85
- ## Example: Error Position Mapping
86
-
87
- ```typescript
50
+ ``` ## Example: Error Position Mapping
51
+ ```
88
52
  import { NativePlugin } from "macroforge";
89
53
 
90
54
  const plugin = new NativePlugin();
@@ -97,7 +61,7 @@ function mapError(filepath: string, expandedPos: number, message: string) {
97
61
  if (mapper.isInGenerated(expandedPos)) {
98
62
  const macroName = mapper.generatedBy(expandedPos);
99
63
  return {
100
- message: \`Error in code generated by @derive(\${macroName}): \${message}\`,
64
+ message: `Error in code generated by @derive(${macroName}): ${message}`,
101
65
  // Find the @derive decorator position
102
66
  position: findDecoratorPosition(filepath)
103
67
  };
@@ -114,14 +78,8 @@ function mapError(filepath: string, expandedPos: number, message: string) {
114
78
 
115
79
  return null;
116
80
  }
117
- ```
118
-
119
- ## Performance
120
-
121
- Position mapping uses binary search with O(log n) complexity:
122
-
123
- - Fast lookups even for large files
124
-
125
- - Minimal memory overhead
126
-
127
- - Thread-safe access
81
+ ``` ## Performance
82
+ Position mapping uses binary search with O(log n) complexity:
83
+ - Fast lookups even for large files
84
+ - Minimal memory overhead
85
+ - Thread-safe access
@@ -1,29 +1,18 @@
1
1
  # transformSync()
2
-
3
- *A lower-level transform function that returns additional metadata alongside the transformed code.*
4
-
5
- ## Signature
6
-
7
- ```typescript
2
+ *Synchronously transforms TypeScript code through the macro expansion system. This is similar to [`expand_sync`] but returns a [`TransformResult`] which includes source map information (when available).*
3
+ ## Signature
4
+ ```
8
5
  function transformSync(
9
6
  code: string,
10
7
  filepath: string
11
8
  ): TransformResult
12
- ```
13
-
14
- ## Parameters
15
-
16
- | `code`
17
- | `string`
18
- | TypeScript source code to transform
19
-
20
- | `filepath`
21
- | `string`
22
- | File path (used for error reporting)
23
-
24
- ## TransformResult
25
-
26
- ```typescript
9
+ ``` ## Parameters
10
+ | Parameter | Type | Description |
11
+ | --- | --- | --- |
12
+ | `code` | `string` | TypeScript source code to transform |
13
+ | `filepath` | `string` | File path (used for error reporting) |
14
+ ## TransformResult
15
+ ```
27
16
  interface TransformResult {
28
17
  // Transformed TypeScript code
29
18
  code: string;
@@ -37,37 +26,23 @@ interface TransformResult {
37
26
  // Macro expansion metadata
38
27
  metadata?: string;
39
28
  }
40
- ```
41
-
42
- ## Comparison with expandSync()
43
-
44
- | Options
45
- | Yes
46
- | No
47
-
48
- | Diagnostics
49
- | Yes
50
- | No
51
-
52
- | Source Mapping
53
- | Yes
54
- | Limited
55
-
56
- | Use Case
57
- | General purpose
58
- | Build tools
59
-
60
- ## Example
61
-
62
- ```typescript
29
+ ``` ## Comparison with expandSync()
30
+ | Feature | `expandSync` | `transformSync` |
31
+ | --- | --- | --- |
32
+ | Options | Yes | No |
33
+ | Diagnostics | Yes | No |
34
+ | Source Mapping | Yes | Limited |
35
+ | Use Case | General purpose | Build tools |
36
+ ## Example
37
+ ```
63
38
  import { transformSync } from "macroforge";
64
39
 
65
- const sourceCode = \`
40
+ const sourceCode = `
66
41
  /** @derive(Debug) */
67
42
  class User {
68
43
  name: string;
69
44
  }
70
- \`;
45
+ `;
71
46
 
72
47
  const result = transformSync(sourceCode, "user.ts");
73
48
 
@@ -83,16 +58,9 @@ if (result.metadata) {
83
58
  const meta = JSON.parse(result.metadata);
84
59
  console.log("Macros expanded:", meta);
85
60
  }
86
- ```
87
-
88
- ## When to Use
89
-
90
- Use `transformSync` when:
91
-
92
- - Building custom integrations
93
-
94
- - You need raw output without diagnostics
95
-
96
- - You're implementing a build tool plugin
97
-
98
- Use `expandSync` for most other use cases, as it provides better error handling.
61
+ ``` ## When to Use
62
+ Use `transformSync` when:
63
+ - Building custom integrations
64
+ - You need raw output without diagnostics
65
+ - You're implementing a build tool plugin
66
+ Use `expandSync` for most other use cases, as it provides better error handling.
@@ -1,121 +1,62 @@
1
1
  # Clone
2
2
 
3
- *The `Clone` macro generates a `clone()` method that creates a copy of the object.*
3
+ The `Clone` macro generates a `clone()` method for deep copying objects.
4
+ This is analogous to Rust's `Clone` trait, providing a way to create
5
+ independent copies of values.
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 | `clone(): ClassName` | Instance method creating a new instance with copied fields |
12
+ | Enum | `cloneEnumName(value: EnumName): EnumName` | Standalone function (enums are primitives, returns value as-is) |
13
+ | Interface | `cloneInterfaceName(value: InterfaceName): InterfaceName` | Standalone function creating a new object literal |
14
+ | Type Alias | `cloneTypeName(value: TypeName): TypeName` | Standalone function with spread copy for objects |
8
15
 
9
- ```typescript
10
- const original = new Point(10, 20);
11
- const copy = original.clone();
12
-
13
- console.log(copy.x, copy.y); // 10, 20
14
- console.log(original === copy); // false (different instances)
15
- ```
16
-
17
- ## How It Works
18
-
19
- The Clone macro:
16
+ ## Configuration
20
17
 
21
- 1. Creates a new instance of the class
18
+ The `functionNamingStyle` option in `macroforge.json` controls naming:
19
+ - `"suffix"` (default): Suffixes with type name (e.g., `cloneMyType`)
20
+ - `"prefix"`: Prefixes with type name (e.g., `myTypeClone`)
21
+ - `"generic"`: Uses TypeScript generics (e.g., `clone<T extends MyType>`)
22
+ - `"namespace"`: Legacy namespace wrapping
22
23
 
23
- 2. Passes all field values to the constructor
24
+ ## Cloning Strategy
24
25
 
25
- 3. Returns the new instance
26
+ The generated clone performs a **shallow copy** of all fields:
26
27
 
27
- This creates a **shallow clone** - primitive values are copied, but object references remain the same.
28
+ - **Primitives** (`string`, `number`, `boolean`): Copied by value
29
+ - **Objects**: Reference is copied (not deep cloned)
30
+ - **Arrays**: Reference is copied (not deep cloned)
28
31
 
29
- ## With Nested Objects
32
+ For deep cloning of nested objects, those objects should also derive `Clone`
33
+ and the caller should clone them explicitly.
30
34
 
31
- <MacroExample before={data.examples.nested.before} after={data.examples.nested.after} />
35
+ ## Example
32
36
 
33
37
  ```typescript
34
- const original = new User("Alice", { city: "NYC", zip: "10001" });
35
- const copy = original.clone();
36
-
37
- // The address object is the same reference
38
- console.log(original.address === copy.address); // true
39
-
40
- // Modifying the copy's address affects the original
41
- copy.address.city = "LA";
42
- console.log(original.address.city); // "LA"
43
- ```
44
-
45
- For deep cloning of nested objects, you would need to implement custom clone methods or use a deep clone utility.
46
-
47
- ## Combining with PartialEq
48
-
49
- Clone works well with PartialEq for creating independent copies that compare as equal:
50
-
51
- <InteractiveMacro code={`/** @derive(Clone, PartialEq) */
38
+ @derive(Clone)
52
39
  class Point {
53
- x: number;
54
- y: number;
55
-
56
- constructor(x: number, y: number) {
57
- this.x = x;
58
- this.y = y;
59
- }
60
- }`} />
61
-
62
- ```typescript
63
- const original = new Point(10, 20);
64
- const copy = original.clone();
65
-
66
- console.log(original === copy); // false (different instances)
67
- console.log(original.equals(copy)); // true (same values)
40
+ x: number;
41
+ y: number;
42
+ }
43
+
44
+ // Generated:
45
+ // clone(): Point {
46
+ // const cloned = Object.create(Object.getPrototypeOf(this));
47
+ // cloned.x = this.x;
48
+ // cloned.y = this.y;
49
+ // return cloned;
50
+ // }
51
+
52
+ const p1 = new Point();
53
+ const p2 = p1.clone(); // Creates a new Point with same values
68
54
  ```
69
55
 
70
- ## Interface Support
71
-
72
- Clone also works with interfaces. For interfaces, a namespace is generated with a `clone` function:
73
-
74
- <MacroExample before={data.examples.interface.before} after={data.examples.interface.after} />
75
-
76
- ```typescript
77
- const original: Point = { x: 10, y: 20 };
78
- const copy = Point.clone(original);
56
+ ## Implementation Notes
79
57
 
80
- console.log(copy.x, copy.y); // 10, 20
81
- console.log(original === copy); // false (different objects)
82
- ```
83
-
84
- ## Enum Support
85
-
86
- Clone also works with enums. For enums, the clone function simply returns the value as-is, since enum values are primitives and don't need cloning:
87
-
88
- <MacroExample before={data.examples.enum.before} after={data.examples.enum.after} />
89
-
90
- ```typescript
91
- const original = Status.Active;
92
- const copy = Status.clone(original);
93
-
94
- console.log(copy); // "active"
95
- console.log(original === copy); // true (same primitive value)
96
- ```
97
-
98
- ## Type Alias Support
99
-
100
- Clone works with type aliases. For object types, a shallow copy is created using spread:
101
-
102
- <MacroExample before={data.examples.typeAlias.before} after={data.examples.typeAlias.after} />
103
-
104
- ```typescript
105
- const original: Point = { x: 10, y: 20 };
106
- const copy = Point.clone(original);
107
-
108
- console.log(copy.x, copy.y); // 10, 20
109
- console.log(original === copy); // false (different objects)
110
- ```
111
-
112
- For union types, the value is returned as-is (unions of primitives don't need cloning):
113
-
114
- <InteractiveMacro code={`/** @derive(Clone) */
115
- type ApiStatus = "loading" | "success" | "error";`} />
116
-
117
- ```typescript
118
- const status: ApiStatus = "success";
119
- const copy = ApiStatus.clone(status);
120
- console.log(copy); // "success"
121
- ```
58
+ - **Classes**: Uses `Object.create(Object.getPrototypeOf(this))` to preserve
59
+ the prototype chain, ensuring `instanceof` checks work correctly
60
+ - **Enums**: Simply returns the value (enums are primitives in TypeScript)
61
+ - **Interfaces/Type Aliases**: Creates new object literals with spread operator
62
+ for union/tuple types, or field-by-field copy for object types
@@ -1,123 +1,52 @@
1
1
  # Debug
2
2
 
3
- *The `Debug` macro generates a `toString()` method that produces a human-readable string representation of your class.*
3
+ The `Debug` macro generates a human-readable `toString()` method for
4
+ TypeScript classes, interfaces, enums, and type aliases.
4
5
 
5
- ## Basic Usage
6
+ ## Generated Output
6
7
 
7
- <MacroExample before={data.examples.basic.before} after={data.examples.basic.after} />
8
+ **Classes**: Generates an instance method returning a string
9
+ like `"ClassName { field1: value1, field2: value2 }"`.
8
10
 
9
- ```typescript
10
- const user = new User("Alice", 30);
11
- console.log(user.toString());
12
- // Output: User { name: Alice, age: 30 }
13
- ```
14
-
15
- ## Field Options
16
-
17
- Use the `@debug` field decorator to customize behavior:
18
-
19
- ### Renaming Fields
20
-
21
- <MacroExample before={data.examples.rename.before} after={data.examples.rename.after} />
22
-
23
- ```typescript
24
- const user = new User(42, "Alice");
25
- console.log(user.toString());
26
- // Output: User { userId: 42, name: Alice }
27
- ```
28
-
29
- ### Skipping Fields
30
-
31
- Use `skip: true` to exclude sensitive fields from the output:
32
-
33
- <MacroExample before={data.examples.skip.before} after={data.examples.skip.after} />
34
-
35
- ```typescript
36
- const user = new User("Alice", "alice@example.com", "secret", "tok_xxx");
37
- console.log(user.toString());
38
- // Output: User { name: Alice, email: alice@example.com }
39
- // Note: password and authToken are not included
40
- ```
41
-
42
- <Alert type="tip" title="Security">
43
- Always skip sensitive fields like passwords, tokens, and API keys to prevent accidental logging.
44
- </Alert>
45
-
46
- ## Combining Options
11
+ **Enums**: Generates a standalone function `toStringEnumName(value)` that performs
12
+ reverse lookup on numeric enums.
47
13
 
48
- <InteractiveMacro code={`/** @derive(Debug) */
49
- class ApiResponse {
50
- /** @debug({ rename: "statusCode" }) */
51
- status: number;
14
+ **Interfaces**: Generates a standalone function `toStringInterfaceName(value)`.
52
15
 
53
- data: unknown;
16
+ **Type Aliases**: Generates a standalone function using JSON.stringify for
17
+ complex types, or field enumeration for object types.
54
18
 
55
- /** @debug({ skip: true }) */
56
- internalMetadata: Record<string, unknown>;
57
- }`} />
19
+ ## Configuration
58
20
 
59
- ## All Options
21
+ The `functionNamingStyle` option in `macroforge.json` controls naming:
22
+ - `"suffix"` (default): Suffixes with type name (e.g., `toStringMyType`)
23
+ - `"prefix"`: Prefixes with type name (e.g., `myTypeToString`)
24
+ - `"generic"`: Uses TypeScript generics (e.g., `toString<T extends MyType>`)
25
+ - `"namespace"`: Legacy namespace wrapping
60
26
 
61
- | `rename`
62
- | `string`
63
- | Display a different name in the output
27
+ ## Field-Level Options
64
28
 
65
- | `skip`
66
- | `boolean`
67
- | Exclude this field from the output
29
+ The `@debug` decorator supports:
68
30
 
69
- ## Interface Support
31
+ - `skip` - Exclude the field from debug output
32
+ - `rename = "label"` - Use a custom label instead of the field name
70
33
 
71
- Debug also works with interfaces. For interfaces, a namespace is generated with a `toString` function:
72
-
73
- <MacroExample before={data.examples.interface.before} after={data.examples.interface.after} />
34
+ ## Example
74
35
 
75
36
  ```typescript
76
- const status: Status = { active: true, message: "OK" };
77
- console.log(Status.toString(status));
78
- // Output: Status { active: true, message: OK }
79
- ```
80
-
81
- ## Enum Support
37
+ @derive(Debug)
38
+ class User {
39
+ @debug(rename = "id")
40
+ userId: number;
82
41
 
83
- Debug also works with enums. For enums, a namespace is generated with a `toString` function that displays the enum name and variant:
42
+ @debug(skip)
43
+ password: string;
84
44
 
85
- <MacroExample before={data.examples.enum.before} after={data.examples.enum.after} />
86
-
87
- ```typescript
88
- console.log(Priority.toString(Priority.High));
89
- // Output: Priority.High
45
+ email: string;
46
+ }
90
47
 
91
- console.log(Priority.toString(Priority.Low));
92
- // Output: Priority.Low
48
+ // Generated:
49
+ // toString(): string {
50
+ // return "User { id: " + this.userId + ", email: " + this.email + " }";
51
+ // }
93
52
  ```
94
-
95
- Works with both numeric and string enums:
96
-
97
- <InteractiveMacro code={`/** @derive(Debug) */
98
- enum Status {
99
- Active = "active",
100
- Inactive = "inactive",
101
- }`} />
102
-
103
- ## Type Alias Support
104
-
105
- Debug works with type aliases. For object types, fields are displayed similar to interfaces:
106
-
107
- <MacroExample before={data.examples.typeAlias.before} after={data.examples.typeAlias.after} />
108
-
109
- ```typescript
110
- const point: Point = { x: 10, y: 20 };
111
- console.log(Point.toString(point));
112
- // Output: Point { x: 10, y: 20 }
113
- ```
114
-
115
- For union types, the value is displayed using JSON.stringify:
116
-
117
- <InteractiveMacro code={`/** @derive(Debug) */
118
- type ApiStatus = "loading" | "success" | "error";`} />
119
-
120
- ```typescript
121
- console.log(ApiStatus.toString("success"));
122
- // Output: ApiStatus("success")
123
- ```