@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.
- package/README.md +68 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +46 -1
- package/dist/index.js.map +1 -1
- package/dist/tools/docs-loader.d.ts +133 -5
- package/dist/tools/docs-loader.d.ts.map +1 -1
- package/dist/tools/docs-loader.js +131 -15
- package/dist/tools/docs-loader.js.map +1 -1
- package/dist/tools/index.d.ts +48 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +163 -14
- package/dist/tools/index.js.map +1 -1
- package/docs/api/api-overview.md +24 -46
- package/docs/api/expand-sync.md +24 -51
- package/docs/api/native-plugin.md +24 -56
- package/docs/api/position-mapper.md +34 -76
- package/docs/api/transform-sync.md +27 -59
- package/docs/builtin-macros/clone.md +45 -104
- package/docs/builtin-macros/debug.md +33 -104
- package/docs/builtin-macros/default.md +78 -114
- package/docs/builtin-macros/deserialize.md +93 -273
- package/docs/builtin-macros/hash.md +58 -100
- package/docs/builtin-macros/macros-overview.md +42 -103
- package/docs/builtin-macros/ord.md +65 -133
- package/docs/builtin-macros/partial-eq.md +53 -179
- package/docs/builtin-macros/partial-ord.md +67 -159
- package/docs/builtin-macros/serialize.md +64 -194
- package/docs/concepts/architecture.md +40 -99
- package/docs/concepts/derive-system.md +129 -125
- package/docs/concepts/how-macros-work.md +52 -84
- package/docs/custom-macros/custom-overview.md +17 -39
- package/docs/custom-macros/rust-setup.md +22 -55
- package/docs/custom-macros/ts-macro-derive.md +43 -107
- package/docs/custom-macros/ts-quote.md +177 -507
- package/docs/getting-started/first-macro.md +108 -33
- package/docs/getting-started/installation.md +32 -73
- package/docs/integration/cli.md +70 -156
- package/docs/integration/configuration.md +32 -75
- package/docs/integration/integration-overview.md +16 -55
- package/docs/integration/mcp-server.md +30 -69
- package/docs/integration/svelte-preprocessor.md +60 -83
- package/docs/integration/typescript-plugin.md +32 -74
- package/docs/integration/vite-plugin.md +30 -79
- package/docs/language-servers/ls-overview.md +22 -46
- package/docs/language-servers/svelte.md +30 -69
- package/docs/language-servers/zed.md +34 -72
- package/docs/roadmap/roadmap.md +54 -130
- package/docs/sections.json +3 -262
- package/package.json +2 -2
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
# PositionMapper
|
|
2
|
-
|
|
3
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
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
|
-
|
|
120
|
-
|
|
121
|
-
|
|
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
|
-
|
|
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
|
-
|
|
15
|
-
|
|
16
|
-
| `
|
|
17
|
-
|
|
18
|
-
|
|
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
|
-
|
|
43
|
-
|
|
44
|
-
|
|
|
45
|
-
| Yes
|
|
46
|
-
|
|
|
47
|
-
|
|
48
|
-
|
|
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
|
-
|
|
89
|
-
|
|
90
|
-
|
|
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
|
-
|
|
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
|
-
##
|
|
7
|
+
## Generated Output
|
|
6
8
|
|
|
7
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
24
|
+
## Cloning Strategy
|
|
24
25
|
|
|
25
|
-
|
|
26
|
+
The generated clone performs a **shallow copy** of all fields:
|
|
26
27
|
|
|
27
|
-
|
|
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
|
-
|
|
32
|
+
For deep cloning of nested objects, those objects should also derive `Clone`
|
|
33
|
+
and the caller should clone them explicitly.
|
|
30
34
|
|
|
31
|
-
|
|
35
|
+
## Example
|
|
32
36
|
|
|
33
37
|
```typescript
|
|
34
|
-
|
|
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
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
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
|
-
##
|
|
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
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
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
|
-
|
|
3
|
+
The `Debug` macro generates a human-readable `toString()` method for
|
|
4
|
+
TypeScript classes, interfaces, enums, and type aliases.
|
|
4
5
|
|
|
5
|
-
##
|
|
6
|
+
## Generated Output
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
**Classes**: Generates an instance method returning a string
|
|
9
|
+
like `"ClassName { field1: value1, field2: value2 }"`.
|
|
8
10
|
|
|
9
|
-
|
|
10
|
-
|
|
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
|
-
|
|
49
|
-
class ApiResponse {
|
|
50
|
-
/** @debug({ rename: "statusCode" }) */
|
|
51
|
-
status: number;
|
|
14
|
+
**Interfaces**: Generates a standalone function `toStringInterfaceName(value)`.
|
|
52
15
|
|
|
53
|
-
|
|
16
|
+
**Type Aliases**: Generates a standalone function using JSON.stringify for
|
|
17
|
+
complex types, or field enumeration for object types.
|
|
54
18
|
|
|
55
|
-
|
|
56
|
-
internalMetadata: Record<string, unknown>;
|
|
57
|
-
}`} />
|
|
19
|
+
## Configuration
|
|
58
20
|
|
|
59
|
-
|
|
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
|
-
|
|
62
|
-
| `string`
|
|
63
|
-
| Display a different name in the output
|
|
27
|
+
## Field-Level Options
|
|
64
28
|
|
|
65
|
-
|
|
66
|
-
| `boolean`
|
|
67
|
-
| Exclude this field from the output
|
|
29
|
+
The `@debug` decorator supports:
|
|
68
30
|
|
|
69
|
-
|
|
31
|
+
- `skip` - Exclude the field from debug output
|
|
32
|
+
- `rename = "label"` - Use a custom label instead of the field name
|
|
70
33
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
<MacroExample before={data.examples.interface.before} after={data.examples.interface.after} />
|
|
34
|
+
## Example
|
|
74
35
|
|
|
75
36
|
```typescript
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
## Enum Support
|
|
37
|
+
@derive(Debug)
|
|
38
|
+
class User {
|
|
39
|
+
@debug(rename = "id")
|
|
40
|
+
userId: number;
|
|
82
41
|
|
|
83
|
-
|
|
42
|
+
@debug(skip)
|
|
43
|
+
password: string;
|
|
84
44
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
```typescript
|
|
88
|
-
console.log(Priority.toString(Priority.High));
|
|
89
|
-
// Output: Priority.High
|
|
45
|
+
email: string;
|
|
46
|
+
}
|
|
90
47
|
|
|
91
|
-
|
|
92
|
-
//
|
|
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
|
-
```
|