@macroforge/mcp-server 0.1.34 → 0.1.36
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/docs/builtin-macros/clone.md +42 -183
- package/docs/builtin-macros/debug.md +33 -239
- package/docs/builtin-macros/default.md +78 -257
- package/docs/builtin-macros/deserialize.md +94 -999
- package/docs/builtin-macros/hash.md +62 -260
- package/docs/builtin-macros/ord.md +70 -251
- package/docs/builtin-macros/partial-eq.md +55 -262
- package/docs/builtin-macros/partial-ord.md +69 -272
- package/docs/builtin-macros/serialize.md +63 -382
- package/docs/concepts/derive-system.md +1 -4
- package/package.json +2 -2
|
@@ -1,203 +1,62 @@
|
|
|
1
1
|
# Clone
|
|
2
|
-
*The `Clone` macro generates a `clone()` method for deep copying objects. This is analogous to Rust's `Clone` trait, providing a way to create independent copies of values.*
|
|
3
|
-
## Basic Usage
|
|
4
|
-
**Before:**
|
|
5
|
-
```
|
|
6
|
-
/** @derive(Clone) */
|
|
7
|
-
class Point {
|
|
8
|
-
x: number;
|
|
9
|
-
y: number;
|
|
10
2
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
```
|
|
17
|
-
**After:**
|
|
18
|
-
```
|
|
19
|
-
class Point {
|
|
20
|
-
x: number;
|
|
21
|
-
y: number;
|
|
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.
|
|
22
6
|
|
|
23
|
-
|
|
24
|
-
this.x = x;
|
|
25
|
-
this.y = y;
|
|
26
|
-
}
|
|
7
|
+
## Generated Output
|
|
27
8
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
``` ```
|
|
36
|
-
const original = new Point(10, 20);
|
|
37
|
-
const copy = original.clone();
|
|
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 |
|
|
38
15
|
|
|
39
|
-
|
|
40
|
-
console.log(original === copy); // false (different instances)
|
|
41
|
-
``` ## How It Works
|
|
42
|
-
The Clone macro:
|
|
43
|
-
1. Creates a new instance of the class
|
|
44
|
-
2. Passes all field values to the constructor
|
|
45
|
-
3. Returns the new instance
|
|
46
|
-
This creates a **shallow clone** - primitive values are copied, but object references remain the same.
|
|
47
|
-
## With Nested Objects
|
|
48
|
-
**Before:**
|
|
49
|
-
```
|
|
50
|
-
/** @derive(Clone) */
|
|
51
|
-
class User {
|
|
52
|
-
name: string;
|
|
53
|
-
address: { city: string; zip: string };
|
|
16
|
+
## Configuration
|
|
54
17
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
```
|
|
61
|
-
**After:**
|
|
62
|
-
```
|
|
63
|
-
class User {
|
|
64
|
-
name: string;
|
|
65
|
-
address: { city: string; zip: string };
|
|
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
|
|
66
23
|
|
|
67
|
-
|
|
68
|
-
this.name = name;
|
|
69
|
-
this.address = address;
|
|
70
|
-
}
|
|
24
|
+
## Cloning Strategy
|
|
71
25
|
|
|
72
|
-
|
|
73
|
-
const cloned = Object.create(Object.getPrototypeOf(this));
|
|
74
|
-
cloned.name = this.name;
|
|
75
|
-
cloned.address = this.address;
|
|
76
|
-
return cloned;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
``` ```
|
|
80
|
-
const original = new User("Alice", { city: "NYC", zip: "10001" });
|
|
81
|
-
const copy = original.clone();
|
|
26
|
+
The generated clone performs a **shallow copy** of all fields:
|
|
82
27
|
|
|
83
|
-
|
|
84
|
-
|
|
28
|
+
- **Primitives** (`string`, `number`, `boolean`): Copied by value
|
|
29
|
+
- **Objects**: Reference is copied (not deep cloned)
|
|
30
|
+
- **Arrays**: Reference is copied (not deep cloned)
|
|
85
31
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
console.log(original.address.city); // "LA"
|
|
89
|
-
``` For deep cloning of nested objects, you would need to implement custom clone methods or use a deep clone utility.
|
|
90
|
-
## Combining with PartialEq
|
|
91
|
-
Clone works well with PartialEq for creating independent copies that compare as equal:
|
|
92
|
-
**Source:**
|
|
93
|
-
```
|
|
94
|
-
/** @derive(Clone, PartialEq) */
|
|
95
|
-
class Point {
|
|
96
|
-
x: number;
|
|
97
|
-
y: number;
|
|
32
|
+
For deep cloning of nested objects, those objects should also derive `Clone`
|
|
33
|
+
and the caller should clone them explicitly.
|
|
98
34
|
|
|
99
|
-
|
|
100
|
-
this.x = x;
|
|
101
|
-
this.y = y;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
``` ```
|
|
105
|
-
const original = new Point(10, 20);
|
|
106
|
-
const copy = original.clone();
|
|
35
|
+
## Example
|
|
107
36
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
Clone also works with interfaces. For interfaces, a namespace is generated with a `clone` function:
|
|
112
|
-
**Before:**
|
|
113
|
-
```
|
|
114
|
-
/** @derive(Clone) */
|
|
115
|
-
interface Point {
|
|
116
|
-
x: number;
|
|
117
|
-
y: number;
|
|
118
|
-
}
|
|
119
|
-
```
|
|
120
|
-
**After:**
|
|
121
|
-
```
|
|
122
|
-
interface Point {
|
|
37
|
+
```typescript
|
|
38
|
+
@derive(Clone)
|
|
39
|
+
class Point {
|
|
123
40
|
x: number;
|
|
124
41
|
y: number;
|
|
125
42
|
}
|
|
126
43
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
const copy = Point.clone(original);
|
|
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
|
+
// }
|
|
135
51
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
``` ## Enum Support
|
|
139
|
-
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:
|
|
140
|
-
**Before:**
|
|
52
|
+
const p1 = new Point();
|
|
53
|
+
const p2 = p1.clone(); // Creates a new Point with same values
|
|
141
54
|
```
|
|
142
|
-
/** @derive(Clone) */
|
|
143
|
-
enum Status {
|
|
144
|
-
Active = 'active',
|
|
145
|
-
Inactive = 'inactive'
|
|
146
|
-
}
|
|
147
|
-
```
|
|
148
|
-
**After:**
|
|
149
|
-
```
|
|
150
|
-
enum Status {
|
|
151
|
-
Active = 'active',
|
|
152
|
-
Inactive = 'inactive'
|
|
153
|
-
}
|
|
154
55
|
|
|
155
|
-
|
|
156
|
-
export function clone(value: Status): Status {
|
|
157
|
-
return value;
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
``` ```
|
|
161
|
-
const original = Status.Active;
|
|
162
|
-
const copy = Status.clone(original);
|
|
56
|
+
## Implementation Notes
|
|
163
57
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
```
|
|
170
|
-
/** @derive(Clone) */
|
|
171
|
-
type Point = {
|
|
172
|
-
x: number;
|
|
173
|
-
y: number;
|
|
174
|
-
};
|
|
175
|
-
```
|
|
176
|
-
**After:**
|
|
177
|
-
```
|
|
178
|
-
type Point = {
|
|
179
|
-
x: number;
|
|
180
|
-
y: number;
|
|
181
|
-
};
|
|
182
|
-
|
|
183
|
-
export namespace Point {
|
|
184
|
-
export function clone(value: Point): Point {
|
|
185
|
-
return { x: value.x, y: value.y };
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
``` ```
|
|
189
|
-
const original: Point = { x: 10, y: 20 };
|
|
190
|
-
const copy = Point.clone(original);
|
|
191
|
-
|
|
192
|
-
console.log(copy.x, copy.y); // 10, 20
|
|
193
|
-
console.log(original === copy); // false (different objects)
|
|
194
|
-
``` For union types, the value is returned as-is (unions of primitives don't need cloning):
|
|
195
|
-
**Source:**
|
|
196
|
-
```
|
|
197
|
-
/** @derive(Clone) */
|
|
198
|
-
type ApiStatus = "loading" | "success" | "error";
|
|
199
|
-
``` ```
|
|
200
|
-
const status: ApiStatus = "success";
|
|
201
|
-
const copy = ApiStatus.clone(status);
|
|
202
|
-
console.log(copy); // "success"
|
|
203
|
-
```
|
|
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,258 +1,52 @@
|
|
|
1
1
|
# Debug
|
|
2
|
-
*The `Debug` macro generates a human-readable `toString()` method for TypeScript classes, interfaces, enums, and type aliases.*
|
|
3
|
-
## Basic Usage
|
|
4
|
-
**Before:**
|
|
5
|
-
```
|
|
6
|
-
/** @derive(Debug) */
|
|
7
|
-
class User {
|
|
8
|
-
name: string;
|
|
9
|
-
age: number;
|
|
10
|
-
|
|
11
|
-
constructor(name: string, age: number) {
|
|
12
|
-
this.name = name;
|
|
13
|
-
this.age = age;
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
```
|
|
17
|
-
**After:**
|
|
18
|
-
```
|
|
19
|
-
class User {
|
|
20
|
-
name: string;
|
|
21
|
-
age: number;
|
|
22
2
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
this.age = age;
|
|
26
|
-
}
|
|
3
|
+
The `Debug` macro generates a human-readable `toString()` method for
|
|
4
|
+
TypeScript classes, interfaces, enums, and type aliases.
|
|
27
5
|
|
|
28
|
-
|
|
29
|
-
const parts: string[] = [];
|
|
30
|
-
parts.push('name: ' + this.name);
|
|
31
|
-
parts.push('age: ' + this.age);
|
|
32
|
-
return 'User { ' + parts.join(', ') + ' }';
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
``` ```
|
|
36
|
-
const user = new User("Alice", 30);
|
|
37
|
-
console.log(user.toString());
|
|
38
|
-
// Output: User { name: Alice, age: 30 }
|
|
39
|
-
``` ## Field Options
|
|
40
|
-
Use the `@debug` field decorator to customize behavior:
|
|
41
|
-
### Renaming Fields
|
|
42
|
-
**Before:**
|
|
43
|
-
```
|
|
44
|
-
/** @derive(Debug) */
|
|
45
|
-
class User {
|
|
46
|
-
/** @debug({ rename: "userId" }) */
|
|
47
|
-
id: number;
|
|
6
|
+
## Generated Output
|
|
48
7
|
|
|
49
|
-
|
|
8
|
+
**Classes**: Generates an instance method returning a string
|
|
9
|
+
like `"ClassName { field1: value1, field2: value2 }"`.
|
|
50
10
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
this.name = name;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
```
|
|
57
|
-
**After:**
|
|
58
|
-
```
|
|
59
|
-
class User {
|
|
60
|
-
id: number;
|
|
11
|
+
**Enums**: Generates a standalone function `toStringEnumName(value)` that performs
|
|
12
|
+
reverse lookup on numeric enums.
|
|
61
13
|
|
|
62
|
-
|
|
14
|
+
**Interfaces**: Generates a standalone function `toStringInterfaceName(value)`.
|
|
63
15
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
this.name = name;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
toString(): string {
|
|
70
|
-
const parts: string[] = [];
|
|
71
|
-
parts.push('userId: ' + this.id);
|
|
72
|
-
parts.push('name: ' + this.name);
|
|
73
|
-
return 'User { ' + parts.join(', ') + ' }';
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
``` ```
|
|
77
|
-
const user = new User(42, "Alice");
|
|
78
|
-
console.log(user.toString());
|
|
79
|
-
// Output: User { userId: 42, name: Alice }
|
|
80
|
-
``` ### Skipping Fields
|
|
81
|
-
Use `skip: true` to exclude sensitive fields from the output:
|
|
82
|
-
**Before:**
|
|
83
|
-
```
|
|
84
|
-
/** @derive(Debug) */
|
|
85
|
-
class User {
|
|
86
|
-
name: string;
|
|
87
|
-
email: string;
|
|
88
|
-
|
|
89
|
-
/** @debug({ skip: true }) */
|
|
90
|
-
password: string;
|
|
91
|
-
|
|
92
|
-
/** @debug({ skip: true }) */
|
|
93
|
-
authToken: string;
|
|
94
|
-
|
|
95
|
-
constructor(name: string, email: string, password: string, authToken: string) {
|
|
96
|
-
this.name = name;
|
|
97
|
-
this.email = email;
|
|
98
|
-
this.password = password;
|
|
99
|
-
this.authToken = authToken;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
```
|
|
103
|
-
**After:**
|
|
104
|
-
```
|
|
105
|
-
class User {
|
|
106
|
-
name: string;
|
|
107
|
-
email: string;
|
|
16
|
+
**Type Aliases**: Generates a standalone function using JSON.stringify for
|
|
17
|
+
complex types, or field enumeration for object types.
|
|
108
18
|
|
|
109
|
-
|
|
19
|
+
## Configuration
|
|
110
20
|
|
|
111
|
-
|
|
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
|
|
112
26
|
|
|
113
|
-
|
|
114
|
-
this.name = name;
|
|
115
|
-
this.email = email;
|
|
116
|
-
this.password = password;
|
|
117
|
-
this.authToken = authToken;
|
|
118
|
-
}
|
|
27
|
+
## Field-Level Options
|
|
119
28
|
|
|
120
|
-
|
|
121
|
-
const parts: string[] = [];
|
|
122
|
-
parts.push('name: ' + this.name);
|
|
123
|
-
parts.push('email: ' + this.email);
|
|
124
|
-
return 'User { ' + parts.join(', ') + ' }';
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
``` ```
|
|
128
|
-
const user = new User("Alice", "alice@example.com", "secret", "tok_xxx");
|
|
129
|
-
console.log(user.toString());
|
|
130
|
-
// Output: User { name: Alice, email: alice@example.com }
|
|
131
|
-
// Note: password and authToken are not included
|
|
132
|
-
``` **Security Always skip sensitive fields like passwords, tokens, and API keys to prevent accidental logging. ## Combining Options
|
|
133
|
-
****Source:**
|
|
134
|
-
```
|
|
135
|
-
/** @derive(Debug) */
|
|
136
|
-
class ApiResponse {
|
|
137
|
-
/** @debug({ rename: "statusCode" }) */
|
|
138
|
-
status: number;
|
|
29
|
+
The `@debug` decorator supports:
|
|
139
30
|
|
|
140
|
-
|
|
31
|
+
- `skip` - Exclude the field from debug output
|
|
32
|
+
- `rename = "label"` - Use a custom label instead of the field name
|
|
141
33
|
|
|
142
|
-
|
|
143
|
-
internalMetadata: Record<string, unknown>;
|
|
144
|
-
}
|
|
145
|
-
``` ## All Options
|
|
146
|
-
| Option | Type | Description |
|
|
147
|
-
| --- | --- | --- |
|
|
148
|
-
| `rename` | `string` | Display a different name in the output |
|
|
149
|
-
| `skip` | `boolean` | Exclude this field from the output |
|
|
150
|
-
## Interface Support
|
|
151
|
-
Debug also works with interfaces. For interfaces, a namespace is generated with a `toString` function:
|
|
152
|
-
**Before:**
|
|
153
|
-
```
|
|
154
|
-
/** @derive(Debug) */
|
|
155
|
-
interface Status {
|
|
156
|
-
active: boolean;
|
|
157
|
-
message: string;
|
|
158
|
-
}
|
|
159
|
-
```
|
|
160
|
-
**After:**
|
|
161
|
-
```
|
|
162
|
-
interface Status {
|
|
163
|
-
active: boolean;
|
|
164
|
-
message: string;
|
|
165
|
-
}
|
|
34
|
+
## Example
|
|
166
35
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
return 'Status { ' + parts.join(', ') + ' }';
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
``` ```
|
|
176
|
-
const status: Status = { active: true, message: "OK" };
|
|
177
|
-
console.log(Status.toString(status));
|
|
178
|
-
// Output: Status { active: true, message: OK }
|
|
179
|
-
``` ## Enum Support
|
|
180
|
-
Debug also works with enums. For enums, a namespace is generated with a `toString` function that displays the enum name and variant:
|
|
181
|
-
**Before:**
|
|
182
|
-
```
|
|
183
|
-
/** @derive(Debug) */
|
|
184
|
-
enum Priority {
|
|
185
|
-
Low = 1,
|
|
186
|
-
Medium = 2,
|
|
187
|
-
High = 3
|
|
188
|
-
}
|
|
189
|
-
```
|
|
190
|
-
**After:**
|
|
191
|
-
```
|
|
192
|
-
enum Priority {
|
|
193
|
-
Low = 1,
|
|
194
|
-
Medium = 2,
|
|
195
|
-
High = 3
|
|
196
|
-
}
|
|
36
|
+
```typescript
|
|
37
|
+
@derive(Debug)
|
|
38
|
+
class User {
|
|
39
|
+
@debug(rename = "id")
|
|
40
|
+
userId: number;
|
|
197
41
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
const key = Priority[value as unknown as keyof typeof Priority];
|
|
201
|
-
if (key !== undefined) {
|
|
202
|
-
return 'Priority.' + key;
|
|
203
|
-
}
|
|
204
|
-
return 'Priority(' + String(value) + ')';
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
``` ```
|
|
208
|
-
console.log(Priority.toString(Priority.High));
|
|
209
|
-
// Output: Priority.High
|
|
42
|
+
@debug(skip)
|
|
43
|
+
password: string;
|
|
210
44
|
|
|
211
|
-
|
|
212
|
-
// Output: Priority.Low
|
|
213
|
-
``` Works with both numeric and string enums:
|
|
214
|
-
**Source:**
|
|
215
|
-
```
|
|
216
|
-
/** @derive(Debug) */
|
|
217
|
-
enum Status {
|
|
218
|
-
Active = "active",
|
|
219
|
-
Inactive = "inactive",
|
|
45
|
+
email: string;
|
|
220
46
|
}
|
|
221
|
-
``` ## Type Alias Support
|
|
222
|
-
Debug works with type aliases. For object types, fields are displayed similar to interfaces:
|
|
223
|
-
**Before:**
|
|
224
|
-
```
|
|
225
|
-
/** @derive(Debug) */
|
|
226
|
-
type Point = {
|
|
227
|
-
x: number;
|
|
228
|
-
y: number;
|
|
229
|
-
};
|
|
230
|
-
```
|
|
231
|
-
**After:**
|
|
232
|
-
```
|
|
233
|
-
type Point = {
|
|
234
|
-
x: number;
|
|
235
|
-
y: number;
|
|
236
|
-
};
|
|
237
47
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
parts.push('y: ' + value.y);
|
|
243
|
-
return 'Point { ' + parts.join(', ') + ' }';
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
``` ```
|
|
247
|
-
const point: Point = { x: 10, y: 20 };
|
|
248
|
-
console.log(Point.toString(point));
|
|
249
|
-
// Output: Point { x: 10, y: 20 }
|
|
250
|
-
``` For union types, the value is displayed using JSON.stringify:
|
|
251
|
-
**Source:**
|
|
48
|
+
// Generated:
|
|
49
|
+
// toString(): string {
|
|
50
|
+
// return "User { id: " + this.userId + ", email: " + this.email + " }";
|
|
51
|
+
// }
|
|
252
52
|
```
|
|
253
|
-
/** @derive(Debug) */
|
|
254
|
-
type ApiStatus = "loading" | "success" | "error";
|
|
255
|
-
``` ```
|
|
256
|
-
console.log(ApiStatus.toString("success"));
|
|
257
|
-
// Output: ApiStatus("success")
|
|
258
|
-
```
|