@saltify/milky-generator 0.1.0 → 0.1.1

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 (2) hide show
  1. package/dist/cli.mjs +461 -507
  2. package/package.json +1 -1
package/dist/cli.mjs CHANGED
@@ -32,58 +32,120 @@ var __copyProps = (to, from, except, desc) => {
32
32
  var __toCommonJS = (mod) => __hasOwnProp.call(mod, "module.exports") ? mod["module.exports"] : __copyProps(__defProp({}, "__esModule", { value: true }), mod);
33
33
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
34
34
  //#endregion
35
- //#region ../common/src/generator/dart/json_serializable.ts
36
- function toLowerCamelCase$2(s) {
37
- return s.replace(/_([a-z])/g, (_, c) => c.toUpperCase());
38
- }
39
- function toUpperCamelCase$2(s) {
40
- const lower = toLowerCamelCase$2(s);
41
- return lower.charAt(0).toUpperCase() + lower.slice(1);
35
+ //#region ../common/src/generator/shared/naming.ts
36
+ const preserveFullCapitalizedWords = new Set(["csrf"]);
37
+ function snakeCaseToLowerCamelCase(value) {
38
+ return value.replace(/_([a-z])/g, (_, char) => char.toUpperCase());
42
39
  }
43
- function formatDartLiteral(value) {
44
- return JSON.stringify(value);
40
+ function snakeCaseToUpperCamelCase(value) {
41
+ const lowerCamelCase = snakeCaseToLowerCamelCase(value);
42
+ return lowerCamelCase.charAt(0).toUpperCase() + lowerCamelCase.slice(1);
45
43
  }
46
- function formatDocComment$1(text) {
47
- return text.split("\n").map((line) => line.trim()).filter((line) => line.length > 0).map((line) => `/// ${line}`);
44
+ function snakeCaseToPascalCase(value) {
45
+ return value.split("_").map((part) => preserveFullCapitalizedWords.has(part) ? part.toUpperCase() : part.charAt(0).toUpperCase() + part.slice(1)).join("");
48
46
  }
49
- function resolveDefaultValue$1(value) {
50
- if (typeof value === "function") return value();
51
- return value;
47
+ function normalizeDerivedStructName(structName, tagValue) {
48
+ const tagValuePascalCase = snakeCaseToPascalCase(tagValue);
49
+ const lastCapitalIndex = structName.split("").reverse().findIndex((char) => char >= "A" && char <= "Z");
50
+ if (lastCapitalIndex === -1) return structName + tagValuePascalCase;
51
+ const insertPosition = structName.length - lastCapitalIndex - 1;
52
+ return structName.slice(0, insertPosition) + tagValuePascalCase + structName.slice(insertPosition);
52
53
  }
53
- function collectArrayUnionRefs$1(ir) {
54
- const unionStructNames = new Set(ir.commonStructs.filter((struct) => struct.structType === "union").map((struct) => struct.name));
55
- const arrayUnionRefs = /* @__PURE__ */ new Set();
56
- const handleFields = (fields) => {
57
- fields.forEach((field) => {
58
- if (field.fieldType === "ref" && field.isArray && unionStructNames.has(field.refStructName)) arrayUnionRefs.add(field.refStructName);
59
- });
54
+ //#endregion
55
+ //#region ../common/src/generator/shared/ir.ts
56
+ function getApiTypeNames(endpoint) {
57
+ const pascalEndpoint = snakeCaseToPascalCase(endpoint);
58
+ return {
59
+ pascalEndpoint,
60
+ inputName: `${pascalEndpoint}Input`,
61
+ outputName: `${pascalEndpoint}Output`,
62
+ requestName: `${pascalEndpoint}Request`,
63
+ responseName: `${pascalEndpoint}Response`
60
64
  };
65
+ }
66
+ function isSameField(first, second) {
67
+ if (first.name !== second.name) return false;
68
+ if (first.fieldType !== second.fieldType) return false;
69
+ if (first.isArray !== second.isArray) return false;
70
+ if (first.isOptional !== second.isOptional) return false;
71
+ if (first.fieldType === "scalar" && second.fieldType === "scalar") return first.scalarType === second.scalarType;
72
+ if (first.fieldType === "ref" && second.fieldType === "ref") return first.refStructName === second.refStructName;
73
+ if (first.fieldType === "enum" && second.fieldType === "enum") return first.values.join("\0") === second.values.join("\0");
74
+ return true;
75
+ }
76
+ function collectUnionStructNames(ir) {
77
+ return new Set(ir.commonStructs.filter((struct) => struct.structType === "union").map((struct) => struct.name));
78
+ }
79
+ function visitAllFieldCollections(ir, visit) {
61
80
  ir.commonStructs.forEach((struct) => {
62
81
  if (struct.structType === "simple") {
63
- handleFields(struct.fields);
82
+ visit(struct.fields);
64
83
  return;
65
84
  }
66
85
  if (struct.unionType === "withData") {
67
- handleFields(struct.baseFields);
86
+ visit(struct.baseFields);
68
87
  struct.derivedTypes.forEach((derivedType) => {
69
- if (derivedType.derivingType === "struct") handleFields(derivedType.fields);
88
+ if (derivedType.derivingType === "struct") visit(derivedType.fields);
70
89
  });
71
90
  return;
72
91
  }
73
92
  struct.derivedStructs.forEach((derivedStruct) => {
74
- handleFields(derivedStruct.fields);
93
+ visit(derivedStruct.fields);
75
94
  });
76
95
  });
77
96
  ir.apiCategories.forEach((category) => {
78
97
  category.apis.forEach((api) => {
79
- if (api.requestFields) handleFields(api.requestFields);
80
- if (api.responseFields) handleFields(api.responseFields);
98
+ if (api.requestFields) visit(api.requestFields);
99
+ if (api.responseFields) visit(api.responseFields);
100
+ });
101
+ });
102
+ }
103
+ function collectArrayUnionRefs(ir, unionStructNames = collectUnionStructNames(ir)) {
104
+ const arrayUnionRefs = /* @__PURE__ */ new Set();
105
+ visitAllFieldCollections(ir, (fields) => {
106
+ fields.forEach((field) => {
107
+ if (field.fieldType === "ref" && field.isArray && unionStructNames.has(field.refStructName)) arrayUnionRefs.add(field.refStructName);
81
108
  });
82
109
  });
83
110
  return arrayUnionRefs;
84
111
  }
112
+ function getPlainUnionCommonFields(struct) {
113
+ if (struct.derivedStructs.length === 0) return [];
114
+ let commonFields = [...struct.derivedStructs[0].fields];
115
+ for (let index = 1; index < struct.derivedStructs.length; index++) commonFields = commonFields.filter((field) => struct.derivedStructs[index].fields.some((candidate) => isSameField(field, candidate)));
116
+ return commonFields;
117
+ }
118
+ //#endregion
119
+ //#region ../common/src/generator/shared/text.ts
120
+ function createLineWriter() {
121
+ const lines = [];
122
+ return {
123
+ lines,
124
+ line(value = "") {
125
+ lines.push(value);
126
+ },
127
+ toString() {
128
+ return lines.join("\n");
129
+ }
130
+ };
131
+ }
132
+ function indentLines(text, indent = " ") {
133
+ return text.split("\n").map((line) => line.trim() ? indent + line : line).join("\n");
134
+ }
135
+ function formatDocComment(text, prefix = "/// ") {
136
+ return text.split("\n").map((line) => line.trim()).filter((line) => line.length > 0).map((line) => `${prefix}${line}`);
137
+ }
138
+ //#endregion
139
+ //#region ../common/src/generator/dart/json_serializable.ts
140
+ function formatDartLiteral(value) {
141
+ return JSON.stringify(value);
142
+ }
143
+ function resolveDefaultValue$1(value) {
144
+ if (typeof value === "function") return value();
145
+ return value;
146
+ }
85
147
  function renderDropBadElementListHelper(typeName) {
86
- const className = toUpperCamelCase$2(typeName);
148
+ const className = snakeCaseToUpperCamelCase(typeName);
87
149
  return [
88
150
  `List<${className}> _dropBad${className}ListFromJson(Object? json) {`,
89
151
  ` if (json == null) {`,
@@ -154,12 +216,12 @@ function getDartTypeSpec(field) {
154
216
  else if (field.scalarType === "string") baseType = "String";
155
217
  else baseType = "int";
156
218
  else if (field.fieldType === "enum") baseType = "String";
157
- else baseType = toUpperCamelCase$2(field.refStructName);
219
+ else baseType = snakeCaseToUpperCamelCase(field.refStructName);
158
220
  return field.isArray ? `List<${baseType}>` : baseType;
159
221
  }
160
222
  function renderFieldLines$1(key, field, unionStructNames, typeOverride) {
161
223
  const lines = [];
162
- const fieldName = toLowerCamelCase$2(key);
224
+ const fieldName = snakeCaseToLowerCamelCase(key);
163
225
  const description = field.description;
164
226
  const baseType = typeOverride ?? getDartTypeSpec(field);
165
227
  const hasDefault = field.defaultValue !== void 0;
@@ -169,19 +231,19 @@ function renderFieldLines$1(key, field, unionStructNames, typeOverride) {
169
231
  const jsonKeyParts = [`name: "${key}"`];
170
232
  if (field.fieldType === "ref" && field.isArray) {
171
233
  if (field.refStructName === "IncomingSegment") jsonKeyParts.push("fromJson: _incomingSegmentListFromJson");
172
- else if (unionStructNames.has(field.refStructName)) jsonKeyParts.push(`fromJson: _dropBad${toUpperCamelCase$2(field.refStructName)}ListFromJson`);
234
+ else if (unionStructNames.has(field.refStructName)) jsonKeyParts.push(`fromJson: _dropBad${snakeCaseToUpperCamelCase(field.refStructName)}ListFromJson`);
173
235
  }
174
- if (description) formatDocComment$1(description).forEach((line) => lines.push(line));
236
+ if (description) formatDocComment(description).forEach((line) => lines.push(line));
175
237
  if (hasDefault) lines.push(`@Default(${formatDartLiteral(resolveDefaultValue$1(field.defaultValue))})`);
176
238
  lines.push(`@JsonKey(${jsonKeyParts.join(", ")})`);
177
239
  lines.push(`${isRequired ? "required " : ""}${dartType} ${fieldName},`);
178
240
  return lines;
179
241
  }
180
242
  function renderIRSimpleStruct$1(name, fields, description, unionStructNames) {
181
- const className = toUpperCamelCase$2(name);
243
+ const className = snakeCaseToUpperCamelCase(name);
182
244
  const entries = fields;
183
245
  const lines = [];
184
- if (description) lines.push(...formatDocComment$1(description));
246
+ if (description) lines.push(...formatDocComment(description));
185
247
  lines.push("@freezed");
186
248
  lines.push(`abstract class ${className} with _$${className} {`);
187
249
  if (entries.length === 0) lines.push(` const factory ${className}() = _${className};`);
@@ -201,21 +263,21 @@ function renderIRSimpleStruct$1(name, fields, description, unionStructNames) {
201
263
  }
202
264
  function renderIRUnionStruct$2(struct, unionStructNames) {
203
265
  const name = struct.name;
204
- const className = toUpperCamelCase$2(name);
266
+ const className = snakeCaseToUpperCamelCase(name);
205
267
  const lines = [];
206
268
  const extraDefs = [];
207
269
  const discriminator = struct.tagFieldName;
208
- if (struct.description) lines.push(...formatDocComment$1(struct.description));
270
+ if (struct.description) lines.push(...formatDocComment(struct.description));
209
271
  lines.push(`@Freezed(unionKey: "${discriminator}")`);
210
272
  lines.push(`abstract class ${className} with _$${className} {`);
211
273
  if (struct.unionType === "withData") struct.derivedTypes.forEach((derivedType, index) => {
212
274
  const variantValue = derivedType.tagValue;
213
- const variantConstructor = toLowerCamelCase$2(variantValue);
214
- const variantClassName = `${className}${toUpperCamelCase$2(variantValue)}`;
275
+ const variantConstructor = snakeCaseToLowerCamelCase(variantValue);
276
+ const variantClassName = `${className}${snakeCaseToUpperCamelCase(variantValue)}`;
215
277
  let dataTypeName;
216
- if (derivedType.derivingType === "ref") dataTypeName = toUpperCamelCase$2(derivedType.refStructName);
278
+ if (derivedType.derivingType === "ref") dataTypeName = snakeCaseToUpperCamelCase(derivedType.refStructName);
217
279
  else {
218
- dataTypeName = `${className}${toUpperCamelCase$2(variantValue)}Data`;
280
+ dataTypeName = `${className}${snakeCaseToUpperCamelCase(variantValue)}Data`;
219
281
  extraDefs.push(renderIRSimpleStruct$1(dataTypeName, derivedType.fields, "", unionStructNames));
220
282
  }
221
283
  lines.push(` @FreezedUnionValue("${variantValue}")`);
@@ -240,8 +302,8 @@ function renderIRUnionStruct$2(struct, unionStructNames) {
240
302
  });
241
303
  else struct.derivedStructs.forEach((derivedStruct, index) => {
242
304
  const variantValue = derivedStruct.tagValue;
243
- const variantConstructor = toLowerCamelCase$2(variantValue);
244
- const variantClassName = `${className}${toUpperCamelCase$2(variantValue)}`;
305
+ const variantConstructor = snakeCaseToLowerCamelCase(variantValue);
306
+ const variantClassName = `${className}${snakeCaseToUpperCamelCase(variantValue)}`;
245
307
  lines.push(` @FreezedUnionValue("${variantValue}")`);
246
308
  lines.push(` const factory ${className}.${variantConstructor}({`);
247
309
  derivedStruct.fields.forEach((field) => {
@@ -262,8 +324,8 @@ function renderIRUnionStruct$2(struct, unionStructNames) {
262
324
  }
263
325
  function generateDartJsonSerializableSpec(ir) {
264
326
  const lines = [];
265
- const unionStructNames = new Set(ir.commonStructs.filter((struct) => struct.structType === "union").map((struct) => struct.name));
266
- const arrayUnionRefs = collectArrayUnionRefs$1(ir);
327
+ const unionStructNames = collectUnionStructNames(ir);
328
+ const arrayUnionRefs = collectArrayUnionRefs(ir);
267
329
  function l(line = "") {
268
330
  lines.push(line);
269
331
  }
@@ -332,11 +394,11 @@ function generateDartJsonSerializableSpec(ir) {
332
394
  l(`// ---- ${category.name} ----`);
333
395
  l();
334
396
  category.apis.forEach((api) => {
335
- const inputName = `${toUpperCamelCase$2(api.endpoint)}Input`;
397
+ const inputName = `${snakeCaseToUpperCamelCase(api.endpoint)}Input`;
336
398
  if (api.requestFields && api.requestFields.length > 0) l(renderIRSimpleStruct$1(inputName, api.requestFields, "", unionStructNames));
337
399
  else l(`typedef ${inputName} = ApiEmptyStruct;`);
338
400
  l();
339
- const outputName = `${toUpperCamelCase$2(api.endpoint)}Output`;
401
+ const outputName = `${snakeCaseToUpperCamelCase(api.endpoint)}Output`;
340
402
  if (api.responseFields && api.responseFields.length > 0) l(renderIRSimpleStruct$1(outputName, api.responseFields, "", unionStructNames));
341
403
  else if (api.responseFields) l(`typedef ${outputName} = ApiEmptyStruct;`);
342
404
  else l(`typedef ${outputName} = ApiEmptyStruct;`);
@@ -357,10 +419,10 @@ function generateDartJsonSerializableSpec(ir) {
357
419
  ir.apiCategories.forEach((category) => {
358
420
  category.apis.forEach((api) => {
359
421
  l(` /// ${api.description}`);
360
- l(` static final ${toLowerCamelCase$2(api.endpoint)} = ApiEndpoint(`);
422
+ l(` static final ${snakeCaseToLowerCamelCase(api.endpoint)} = ApiEndpoint(`);
361
423
  l(` "/${api.endpoint}",`);
362
- l(` ${toUpperCamelCase$2(api.endpoint)}Input.fromJson,`);
363
- l(` (${toUpperCamelCase$2(api.endpoint)}Output output) => output.toJson(),`);
424
+ l(` ${snakeCaseToUpperCamelCase(api.endpoint)}Input.fromJson,`);
425
+ l(` (${snakeCaseToUpperCamelCase(api.endpoint)}Output output) => output.toJson(),`);
364
426
  l(" );");
365
427
  });
366
428
  });
@@ -2334,7 +2396,7 @@ const ZodType = /* @__PURE__ */ $constructor("ZodType", (inst, def) => {
2334
2396
  inst.array = () => array(inst);
2335
2397
  inst.or = (arg) => union([inst, arg]);
2336
2398
  inst.and = (arg) => intersection(inst, arg);
2337
- inst.transform = (tx) => pipe(inst, transform$2(tx));
2399
+ inst.transform = (tx) => pipe(inst, transform$1(tx));
2338
2400
  inst.default = (def) => _default(inst, def);
2339
2401
  inst.prefault = (def) => prefault(inst, def);
2340
2402
  inst.catch = (params) => _catch(inst, params);
@@ -2431,7 +2493,7 @@ const ZodTransform = /* @__PURE__ */ $constructor("ZodTransform", (inst, def) =>
2431
2493
  return payload;
2432
2494
  };
2433
2495
  });
2434
- function transform$2(fn) {
2496
+ function transform$1(fn) {
2435
2497
  return new ZodTransform({
2436
2498
  type: "transform",
2437
2499
  transform: fn
@@ -2569,246 +2631,6 @@ function superRefine(fn) {
2569
2631
  return /* @__PURE__ */ _superRefine(fn);
2570
2632
  }
2571
2633
  //#endregion
2572
- //#region ../common/src/generator/typescript/common.ts
2573
- const preserveFullCapitalizedWords$2 = ["csrf"];
2574
- function snakeCaseToPascalCase$2(snakeCase) {
2575
- return snakeCase.split("_").map((part) => preserveFullCapitalizedWords$2.includes(part) ? part.toUpperCase() : part.charAt(0).toUpperCase() + part.slice(1)).join("");
2576
- }
2577
- function normalizeDerivedStructName(structName, tagValue) {
2578
- const tagValuePascalCase = snakeCaseToPascalCase$2(tagValue);
2579
- const lastCapitalIndex = structName.split("").reverse().findIndex((char) => char >= "A" && char <= "Z");
2580
- if (lastCapitalIndex === -1) return structName + tagValuePascalCase;
2581
- const insertPosition = structName.length - lastCapitalIndex - 1;
2582
- return structName.slice(0, insertPosition) + tagValuePascalCase + structName.slice(insertPosition);
2583
- }
2584
- function getTypeScriptTypeProjection(field) {
2585
- if (field.fieldType === "scalar") if (field.scalarType === "string") return "string";
2586
- else if (field.scalarType === "bool") return "boolean";
2587
- else return "number";
2588
- else if (field.fieldType === "enum") return field.values.map((v) => `'${v}'`).join(" | ");
2589
- else return field.refStructName;
2590
- }
2591
- //#endregion
2592
- //#region ../common/src/generator/typescript/zod.ts
2593
- const applyDropBadElementArrayStructs = ["GroupNotification"];
2594
- const specialReplacements = new Map([["IncomingReplySegmentData.segments", " " + `get segments() {
2595
- return z.array(z.lazy(() => IncomingSegment)).describe('回复消息内容');
2596
- },`.trim()], ["OutgoingForwardSegmentData.messages", " " + `get messages() {
2597
- return z.array(z.lazy(() => OutgoingForwardedMessage)).describe('合并转发消息内容');
2598
- },`.trim()]]);
2599
- function useLines$1() {
2600
- const lines = [];
2601
- function l(line = "") {
2602
- lines.push(line);
2603
- }
2604
- return [lines, l];
2605
- }
2606
- function getZodTypeSpec(ir, field) {
2607
- let typeSpec = "z.unknown()";
2608
- if (field.fieldType === "scalar") if (field.dataType !== void 0) typeSpec = `z${snakeCaseToPascalCase$2(field.dataType)}`;
2609
- else if (field.scalarType === "string") typeSpec = "z.string()";
2610
- else if (field.scalarType === "bool") typeSpec = "z.boolean()";
2611
- else typeSpec = "z.number().int().nonnegative()";
2612
- else if (field.fieldType === "enum") typeSpec = `z.enum([${field.values.map((v) => `'${v}'`).join(", ")}])`;
2613
- else typeSpec = `z.lazy(() => ${field.refStructName})`;
2614
- if (field.isArray) if (field.fieldType === "ref") {
2615
- const referredStruct = ir.commonStructs.find((s) => s.name === field.refStructName);
2616
- if (applyDropBadElementArrayStructs.includes(referredStruct.name)) typeSpec = `zDropBadElementArray(${field.refStructName})`;
2617
- else typeSpec = `z.array(${typeSpec})`;
2618
- } else typeSpec = `z.array(${typeSpec})`;
2619
- if (field.isOptional) typeSpec += ".nullish()";
2620
- else if (field.defaultValue !== void 0) typeSpec += `.nullish().default(${JSON.stringify(field.defaultValue).replace(/"/g, "'")}).transform<${getTypeScriptTypeProjection(field)}>((val) => val ?? ${JSON.stringify(field.defaultValue).replace(/"/g, "'")})`;
2621
- return typeSpec;
2622
- }
2623
- function renderIRObject$1(ir, name, fields, description, withDescription = true, unionTagFieldName, unionTagValue) {
2624
- const [lines, l] = useLines$1();
2625
- l("z.object({");
2626
- if (unionTagFieldName && unionTagValue) l(` ${unionTagFieldName}: z.literal('${unionTagValue}'),`);
2627
- fields.forEach((field) => {
2628
- const specialKey = `${name}.${field.name}`;
2629
- if (specialReplacements.has(specialKey)) l(specialReplacements.get(specialKey));
2630
- else l(` ${field.name}: ${getZodTypeSpec(ir, field)}.describe('${field.description}'),`);
2631
- });
2632
- if (withDescription) l(`}).describe('${description}')`);
2633
- else l("})");
2634
- return lines.join("\n");
2635
- }
2636
- function generateTypeScriptZodSpec(ir) {
2637
- const [lines, l] = useLines$1();
2638
- l(`// Generated from Milky ${ir.milkyVersion} (${ir.milkyPackageVersion})`);
2639
- l(`
2640
- import { z } from 'zod';
2641
-
2642
- export const milkyVersion = '${ir.milkyVersion}';
2643
- export const milkyPackageVersion = '${ir.milkyPackageVersion}';
2644
-
2645
- export const zUin = z.number().int().min(10001).max(4294967295);
2646
-
2647
- export function zDropBadElementArray<const T extends z.ZodDiscriminatedUnion>(element: T) {
2648
- const schema = z.array(element.catch(null as never)).transform((val) => val.filter((item) => item !== null));
2649
- return schema as unknown as z.ZodPipe<z.ZodArray<z.ZodCatch<z.ZodLazy<T>>>, z.ZodArray<z.ZodLazy<T>>>;
2650
- }
2651
- `.trim());
2652
- l();
2653
- l("// ####################################");
2654
- l("// Common Structs");
2655
- l("// ####################################");
2656
- l();
2657
- ir.commonStructs.forEach((struct) => {
2658
- if (struct.structType === "simple") {
2659
- l(`export const ${struct.name} = ${renderIRObject$1(ir, struct.name, struct.fields, struct.description, true)};`);
2660
- l(`export type ${struct.name} = z.infer<typeof ${struct.name}>;`);
2661
- } else {
2662
- if (struct.unionType === "plain") {
2663
- struct.derivedStructs.forEach((derived) => {
2664
- l(`export const ${normalizeDerivedStructName(struct.name, derived.tagValue)} = ${renderIRObject$1(ir, struct.name, derived.fields, derived.description, true, struct.tagFieldName, derived.tagValue)};`);
2665
- l(`export type ${normalizeDerivedStructName(struct.name, derived.tagValue)} = z.infer<typeof ${normalizeDerivedStructName(struct.name, derived.tagValue)}>;`);
2666
- l();
2667
- });
2668
- l(`export const ${struct.name} = z.discriminatedUnion('${struct.tagFieldName}', [`);
2669
- struct.derivedStructs.forEach((derived) => {
2670
- l(` ${normalizeDerivedStructName(struct.name, derived.tagValue)},`);
2671
- });
2672
- } else {
2673
- struct.derivedTypes.forEach((derived) => {
2674
- const structName = normalizeDerivedStructName(struct.name, derived.tagValue) + "Data";
2675
- if (derived.derivingType === "struct") {
2676
- l(`export const ${structName} = ${renderIRObject$1(ir, structName, derived.fields, derived.description, true)};`);
2677
- l(`export type ${structName} = z.infer<typeof ${structName}>;`);
2678
- l();
2679
- if (struct.name === "Event") {
2680
- l(`export const ${normalizeDerivedStructName(struct.name, derived.tagValue)} = ${structName};`);
2681
- l(`export type ${normalizeDerivedStructName(struct.name, derived.tagValue)} = z.infer<typeof ${structName}>;`);
2682
- l();
2683
- }
2684
- }
2685
- });
2686
- l(`export const ${struct.name} = z.discriminatedUnion('${struct.tagFieldName}', [`);
2687
- struct.derivedTypes.forEach((derived, index) => {
2688
- l(" z.object({");
2689
- l(` ${struct.tagFieldName}: z.literal('${derived.tagValue}'),`);
2690
- struct.baseFields.forEach((field) => {
2691
- l(` ${field.name}: ${getZodTypeSpec(ir, field)}.describe('${field.description}'),`);
2692
- });
2693
- if (derived.derivingType === "struct") {
2694
- l(` data: ${normalizeDerivedStructName(struct.name, derived.tagValue)}Data.describe('${derived.description}'),`);
2695
- l(` }).describe('${derived.description}'),`);
2696
- } else {
2697
- l(` data: z.lazy(() => ${derived.refStructName}).describe('${derived.description}'),`);
2698
- l(` }).describe('${derived.description}'),`);
2699
- }
2700
- if (index !== struct.derivedTypes.length - 1) l();
2701
- });
2702
- }
2703
- if (struct.name === "IncomingSegment") {
2704
- l("]).catch({");
2705
- l(" type: 'text',");
2706
- l(" data: { text: '[unknown]' },");
2707
- l(`}).describe('${struct.description}');`);
2708
- } else l(`]).describe('${struct.description}');`);
2709
- l(`export type ${struct.name} = z.infer<typeof ${struct.name}>;`);
2710
- }
2711
- l();
2712
- });
2713
- l("// ####################################");
2714
- l("// API Structs");
2715
- l("// ####################################");
2716
- l();
2717
- ir.apiCategories.forEach((category) => {
2718
- category.apis.forEach((spec) => {
2719
- const pascalEndpoint = snakeCaseToPascalCase$2(spec.endpoint);
2720
- if (spec.requestFields) {
2721
- l(`export const ${pascalEndpoint}Input = ` + renderIRObject$1(ir, `${pascalEndpoint}Input`, spec.requestFields, spec.endpoint + " 请求参数", true) + ";");
2722
- l(`export type ${pascalEndpoint}Input = z.infer<typeof ${pascalEndpoint}Input>;`);
2723
- l();
2724
- }
2725
- if (spec.responseFields) {
2726
- l(`export const ${pascalEndpoint}Output = ` + renderIRObject$1(ir, `${pascalEndpoint}Output`, spec.responseFields, spec.endpoint + " 响应数据", true) + ";");
2727
- l(`export type ${pascalEndpoint}Output = z.infer<typeof ${pascalEndpoint}Output>;`);
2728
- l();
2729
- }
2730
- });
2731
- });
2732
- l("// ####################################");
2733
- l("// Meta Information");
2734
- l("// ####################################");
2735
- l();
2736
- l("export const zodCommonStructs = {");
2737
- ir.commonStructs.forEach((struct) => {
2738
- l(` ${struct.name},`);
2739
- });
2740
- l("};");
2741
- l();
2742
- l("export const zodApiCategories = {");
2743
- ir.apiCategories.forEach((category) => {
2744
- l(` ${category.key}: {`);
2745
- l(` name: '${category.name}',`);
2746
- l(" apis: {");
2747
- category.apis.forEach((spec) => {
2748
- l(` ${spec.endpoint}: {`);
2749
- l(` description: '${spec.description}',`);
2750
- l(` requestSchema: ${spec.requestFields ? `${snakeCaseToPascalCase$2(spec.endpoint)}Input` : "null"},`);
2751
- l(` responseSchema: ${spec.responseFields ? `${snakeCaseToPascalCase$2(spec.endpoint)}Output` : "null"},`);
2752
- l(" },");
2753
- });
2754
- l(" },");
2755
- l(" },");
2756
- });
2757
- l("};");
2758
- l();
2759
- return lines.join("\n");
2760
- }
2761
- //#endregion
2762
- //#region ../common/src/generator/common.ts
2763
- const preserveFullCapitalizedWords$1 = ["csrf"];
2764
- function snakeCaseToPascalCase$1(snakeCase) {
2765
- return snakeCase.split("_").map((part) => preserveFullCapitalizedWords$1.includes(part) ? part.toUpperCase() : part.charAt(0).toUpperCase() + part.slice(1)).join("");
2766
- }
2767
- async function importCodeAsModule(code) {
2768
- return await import("data:text/javascript," + encodeURIComponent(code));
2769
- }
2770
- function initRegistry(ir, t) {
2771
- globalRegistry._idmap.clear();
2772
- ir.commonStructs.forEach((struct) => {
2773
- let schema = t[struct.name];
2774
- globalRegistry.add(schema, {
2775
- id: struct.name,
2776
- title: schema.description,
2777
- description: schema.description
2778
- });
2779
- if (schema instanceof ZodCatch) schema = schema.def.innerType;
2780
- if (schema instanceof ZodDiscriminatedUnion) schema.options.forEach((option) => {
2781
- const optionAsZodObject = option;
2782
- globalRegistry.add(optionAsZodObject, {
2783
- title: optionAsZodObject.description,
2784
- description: optionAsZodObject.description
2785
- });
2786
- });
2787
- });
2788
- ir.apiCategories.forEach((category) => {
2789
- category.apis.forEach((spec) => {
2790
- if (spec.requestFields !== void 0) {
2791
- const requestId = `${snakeCaseToPascalCase$1(spec.endpoint)}Input`;
2792
- const inputSchema = t[requestId];
2793
- globalRegistry.add(inputSchema, {
2794
- id: requestId,
2795
- title: `${spec.endpoint} 请求参数`,
2796
- description: `${spec.description} API 请求参数`
2797
- });
2798
- }
2799
- if (spec.responseFields !== void 0) {
2800
- const outputId = `${snakeCaseToPascalCase$1(spec.endpoint)}Output`;
2801
- const outputSchema = t[outputId];
2802
- globalRegistry.add(outputSchema, {
2803
- id: outputId,
2804
- title: `${spec.endpoint} 响应数据`,
2805
- description: `${spec.description} API 响应数据`
2806
- });
2807
- }
2808
- });
2809
- });
2810
- }
2811
- //#endregion
2812
2634
  //#region ../node_modules/.pnpm/sucrase@3.35.1/node_modules/sucrase/dist/parser/tokenizer/keywords.js
2813
2635
  var require_keywords = /* @__PURE__ */ __commonJSMin(((exports) => {
2814
2636
  Object.defineProperty(exports, "__esModule", { value: true });
@@ -23786,7 +23608,7 @@ var require_getTSImportedNames = /* @__PURE__ */ __commonJSMin(((exports) => {
23786
23608
  }
23787
23609
  }));
23788
23610
  //#endregion
23789
- //#region ../common/src/generator/json-schema/index.ts
23611
+ //#region ../common/src/generator/typescript/shared.ts
23790
23612
  var import_dist = (/* @__PURE__ */ __commonJSMin(((exports) => {
23791
23613
  Object.defineProperty(exports, "__esModule", { value: true });
23792
23614
  function _interopRequireDefault(obj) {
@@ -23860,12 +23682,243 @@ var import_dist = (/* @__PURE__ */ __commonJSMin(((exports) => {
23860
23682
  };
23861
23683
  }
23862
23684
  })))();
23863
- async function initTypesModule$1(ir) {
23685
+ function getTypeScriptTypeProjection(field) {
23686
+ if (field.fieldType === "scalar") {
23687
+ if (field.scalarType === "string") return "string";
23688
+ if (field.scalarType === "bool") return "boolean";
23689
+ return "number";
23690
+ }
23691
+ if (field.fieldType === "enum") return field.values.map((value) => `'${value}'`).join(" | ");
23692
+ return field.refStructName;
23693
+ }
23694
+ //#endregion
23695
+ //#region ../common/src/generator/typescript/zod.ts
23696
+ const applyDropBadElementArrayStructNames = new Set(["GroupNotification"]);
23697
+ const specialReplacements = new Map([["IncomingReplySegmentData.segments", " " + `get segments() {
23698
+ return z.array(z.lazy(() => IncomingSegment)).describe('回复消息内容');
23699
+ },`.trim()], ["OutgoingForwardSegmentData.messages", " " + `get messages() {
23700
+ return z.array(z.lazy(() => OutgoingForwardedMessage)).describe('合并转发消息内容');
23701
+ },`.trim()]]);
23702
+ function formatTypeScriptLiteral(value) {
23703
+ return JSON.stringify(value).replace(/"/g, "'");
23704
+ }
23705
+ function getZodTypeSpec(ir, field, options = {}) {
23706
+ let typeSpec = "z.unknown()";
23707
+ if (field.fieldType === "scalar") if (field.dataType !== void 0) typeSpec = `z${snakeCaseToPascalCase(field.dataType)}`;
23708
+ else if (field.scalarType === "string") typeSpec = "z.string()";
23709
+ else if (field.scalarType === "bool") typeSpec = "z.boolean()";
23710
+ else typeSpec = "z.number().int().nonnegative()";
23711
+ else if (field.fieldType === "enum") typeSpec = `z.enum([${field.values.map((value) => `'${value}'`).join(", ")}])`;
23712
+ else typeSpec = `z.lazy(() => ${field.refStructName})`;
23713
+ if (field.isArray) if (field.fieldType === "ref") {
23714
+ const referredStruct = ir.commonStructs.find((struct) => struct.name === field.refStructName);
23715
+ if (options.dropBadElementArrayStructNames?.has(referredStruct.name)) typeSpec = `zDropBadElementArray(${field.refStructName})`;
23716
+ else typeSpec = `z.array(${typeSpec})`;
23717
+ } else typeSpec = `z.array(${typeSpec})`;
23718
+ if (field.isOptional) typeSpec += ".nullish()";
23719
+ else if (field.defaultValue !== void 0) {
23720
+ const defaultValueLiteral = formatTypeScriptLiteral(field.defaultValue);
23721
+ typeSpec += `.nullish().default(${defaultValueLiteral}).transform<${getTypeScriptTypeProjection(field)}>((val) => val ?? ${defaultValueLiteral})`;
23722
+ }
23723
+ return typeSpec;
23724
+ }
23725
+ function renderIRObject$1(ir, name, fields, description, withDescription = true, unionTagFieldName, unionTagValue) {
23726
+ const writer = createLineWriter();
23727
+ const l = writer.line;
23728
+ l("z.object({");
23729
+ if (unionTagFieldName && unionTagValue) l(` ${unionTagFieldName}: z.literal('${unionTagValue}'),`);
23730
+ fields.forEach((field) => {
23731
+ const specialKey = `${name}.${field.name}`;
23732
+ if (specialReplacements.has(specialKey)) l(specialReplacements.get(specialKey));
23733
+ else l(` ${field.name}: ${getZodTypeSpec(ir, field, { dropBadElementArrayStructNames: applyDropBadElementArrayStructNames })}.describe('${field.description}'),`);
23734
+ });
23735
+ if (withDescription) l(`}).describe('${description}')`);
23736
+ else l("})");
23737
+ return writer.toString();
23738
+ }
23739
+ function generateTypeScriptZodSpec(ir) {
23740
+ const writer = createLineWriter();
23741
+ const l = writer.line;
23742
+ l(`// Generated from Milky ${ir.milkyVersion} (${ir.milkyPackageVersion})`);
23743
+ l("import { z } from 'zod';");
23744
+ l();
23745
+ l(`export const milkyVersion = '${ir.milkyVersion}';`);
23746
+ l(`export const milkyPackageVersion = '${ir.milkyPackageVersion}';`);
23747
+ l();
23748
+ l("export const zUin = z.number().int().min(10001).max(4294967295);");
23749
+ l();
23750
+ l("export function zDropBadElementArray<const T extends z.ZodDiscriminatedUnion>(element: T) {");
23751
+ l(" const schema = z.array(element.catch(null as never)).transform((val) => val.filter((item) => item !== null));");
23752
+ l(" return schema as unknown as z.ZodPipe<z.ZodArray<z.ZodCatch<z.ZodLazy<T>>>, z.ZodArray<z.ZodLazy<T>>>;");
23753
+ l("}");
23754
+ l();
23755
+ l("// ####################################");
23756
+ l("// Common Structs");
23757
+ l("// ####################################");
23758
+ l();
23759
+ ir.commonStructs.forEach((struct) => {
23760
+ if (struct.structType === "simple") {
23761
+ l(`export const ${struct.name} = ${renderIRObject$1(ir, struct.name, struct.fields, struct.description, true)};`);
23762
+ l(`export type ${struct.name} = z.infer<typeof ${struct.name}>;`);
23763
+ } else {
23764
+ if (struct.unionType === "plain") {
23765
+ struct.derivedStructs.forEach((derived) => {
23766
+ l(`export const ${normalizeDerivedStructName(struct.name, derived.tagValue)} = ${renderIRObject$1(ir, struct.name, derived.fields, derived.description, true, struct.tagFieldName, derived.tagValue)};`);
23767
+ l(`export type ${normalizeDerivedStructName(struct.name, derived.tagValue)} = z.infer<typeof ${normalizeDerivedStructName(struct.name, derived.tagValue)}>;`);
23768
+ l();
23769
+ });
23770
+ l(`export const ${struct.name} = z.discriminatedUnion('${struct.tagFieldName}', [`);
23771
+ struct.derivedStructs.forEach((derived) => {
23772
+ l(` ${normalizeDerivedStructName(struct.name, derived.tagValue)},`);
23773
+ });
23774
+ } else {
23775
+ struct.derivedTypes.forEach((derived) => {
23776
+ const structName = normalizeDerivedStructName(struct.name, derived.tagValue) + "Data";
23777
+ if (derived.derivingType === "struct") {
23778
+ l(`export const ${structName} = ${renderIRObject$1(ir, structName, derived.fields, derived.description, true)};`);
23779
+ l(`export type ${structName} = z.infer<typeof ${structName}>;`);
23780
+ l();
23781
+ if (struct.name === "Event") {
23782
+ l(`export const ${normalizeDerivedStructName(struct.name, derived.tagValue)} = ${structName};`);
23783
+ l(`export type ${normalizeDerivedStructName(struct.name, derived.tagValue)} = z.infer<typeof ${structName}>;`);
23784
+ l();
23785
+ }
23786
+ }
23787
+ });
23788
+ l(`export const ${struct.name} = z.discriminatedUnion('${struct.tagFieldName}', [`);
23789
+ struct.derivedTypes.forEach((derived, index) => {
23790
+ l(" z.object({");
23791
+ l(` ${struct.tagFieldName}: z.literal('${derived.tagValue}'),`);
23792
+ struct.baseFields.forEach((field) => {
23793
+ l(` ${field.name}: ${getZodTypeSpec(ir, field, { dropBadElementArrayStructNames: applyDropBadElementArrayStructNames })}.describe('${field.description}'),`);
23794
+ });
23795
+ if (derived.derivingType === "struct") {
23796
+ l(` data: ${normalizeDerivedStructName(struct.name, derived.tagValue)}Data.describe('${derived.description}'),`);
23797
+ l(` }).describe('${derived.description}'),`);
23798
+ } else {
23799
+ l(` data: z.lazy(() => ${derived.refStructName}).describe('${derived.description}'),`);
23800
+ l(` }).describe('${derived.description}'),`);
23801
+ }
23802
+ if (index !== struct.derivedTypes.length - 1) l();
23803
+ });
23804
+ }
23805
+ if (struct.name === "IncomingSegment") {
23806
+ l("]).catch({");
23807
+ l(" type: 'text',");
23808
+ l(" data: { text: '[unknown]' },");
23809
+ l(`}).describe('${struct.description}');`);
23810
+ } else l(`]).describe('${struct.description}');`);
23811
+ l(`export type ${struct.name} = z.infer<typeof ${struct.name}>;`);
23812
+ }
23813
+ l();
23814
+ });
23815
+ l("// ####################################");
23816
+ l("// API Structs");
23817
+ l("// ####################################");
23818
+ l();
23819
+ ir.apiCategories.forEach((category) => {
23820
+ category.apis.forEach((spec) => {
23821
+ const typeNames = getApiTypeNames(spec.endpoint);
23822
+ if (spec.requestFields) {
23823
+ l(`export const ${typeNames.inputName} = ` + renderIRObject$1(ir, typeNames.inputName, spec.requestFields, spec.endpoint + " 请求参数", true) + ";");
23824
+ l(`export type ${typeNames.inputName} = z.infer<typeof ${typeNames.inputName}>;`);
23825
+ l();
23826
+ }
23827
+ if (spec.responseFields) {
23828
+ l(`export const ${typeNames.outputName} = ` + renderIRObject$1(ir, typeNames.outputName, spec.responseFields, spec.endpoint + " 响应数据", true) + ";");
23829
+ l(`export type ${typeNames.outputName} = z.infer<typeof ${typeNames.outputName}>;`);
23830
+ l();
23831
+ }
23832
+ });
23833
+ });
23834
+ l("// ####################################");
23835
+ l("// Meta Information");
23836
+ l("// ####################################");
23837
+ l();
23838
+ l("export const zodCommonStructs = {");
23839
+ ir.commonStructs.forEach((struct) => {
23840
+ l(` ${struct.name},`);
23841
+ });
23842
+ l("};");
23843
+ l();
23844
+ l("export const zodApiCategories = {");
23845
+ ir.apiCategories.forEach((category) => {
23846
+ l(` ${category.key}: {`);
23847
+ l(` name: '${category.name}',`);
23848
+ l(" apis: {");
23849
+ category.apis.forEach((spec) => {
23850
+ const typeNames = getApiTypeNames(spec.endpoint);
23851
+ l(` ${spec.endpoint}: {`);
23852
+ l(` description: '${spec.description}',`);
23853
+ l(` requestSchema: ${spec.requestFields ? typeNames.inputName : "null"},`);
23854
+ l(` responseSchema: ${spec.responseFields ? typeNames.outputName : "null"},`);
23855
+ l(" },");
23856
+ });
23857
+ l(" },");
23858
+ l(" },");
23859
+ });
23860
+ l("};");
23861
+ l();
23862
+ return writer.toString();
23863
+ }
23864
+ //#endregion
23865
+ //#region ../common/src/generator/shared/zod-runtime.ts
23866
+ const dynamicImport = new Function("specifier", "return import(specifier);");
23867
+ async function importCodeAsModule(code) {
23868
+ return await dynamicImport("data:text/javascript," + encodeURIComponent(code));
23869
+ }
23870
+ async function loadGeneratedZodTypesModule(ir) {
23864
23871
  const { code } = (0, import_dist.transform)(generateTypeScriptZodSpec(ir), { transforms: ["typescript"] });
23865
23872
  return await importCodeAsModule(code.replace("'zod'", `'${import.meta.resolve("zod")}'`));
23866
23873
  }
23874
+ function initializeZodRegistry(ir, typesModule) {
23875
+ globalRegistry._idmap.clear();
23876
+ ir.commonStructs.forEach((struct) => {
23877
+ let schema = typesModule[struct.name];
23878
+ globalRegistry.add(schema, {
23879
+ id: struct.name,
23880
+ title: schema.description,
23881
+ description: schema.description
23882
+ });
23883
+ if (schema instanceof ZodCatch) schema = schema.def.innerType;
23884
+ if (schema instanceof ZodDiscriminatedUnion) schema.options.forEach((option) => {
23885
+ const optionAsZodObject = option;
23886
+ globalRegistry.add(optionAsZodObject, {
23887
+ title: optionAsZodObject.description,
23888
+ description: optionAsZodObject.description
23889
+ });
23890
+ });
23891
+ });
23892
+ ir.apiCategories.forEach((category) => {
23893
+ category.apis.forEach((api) => {
23894
+ const typeNames = getApiTypeNames(api.endpoint);
23895
+ if (api.requestFields !== void 0) {
23896
+ const inputSchema = typesModule[typeNames.inputName];
23897
+ globalRegistry.add(inputSchema, {
23898
+ id: typeNames.inputName,
23899
+ title: `${api.endpoint} 请求参数`,
23900
+ description: `${api.description} API 请求参数`
23901
+ });
23902
+ }
23903
+ if (api.responseFields !== void 0) {
23904
+ const outputSchema = typesModule[typeNames.outputName];
23905
+ globalRegistry.add(outputSchema, {
23906
+ id: typeNames.outputName,
23907
+ title: `${api.endpoint} 响应数据`,
23908
+ description: `${api.description} API 响应数据`
23909
+ });
23910
+ }
23911
+ });
23912
+ });
23913
+ }
23914
+ function sanitizeGeneratedSchema(schema) {
23915
+ const { $schema, ...rest } = schema;
23916
+ return rest;
23917
+ }
23918
+ //#endregion
23919
+ //#region ../common/src/generator/json-schema/index.ts
23867
23920
  async function generateJsonSchema(ir, typesModule) {
23868
- initRegistry(ir, typesModule ?? await initTypesModule$1(ir));
23921
+ initializeZodRegistry(ir, typesModule ?? await loadGeneratedZodTypesModule(ir));
23869
23922
  return {
23870
23923
  milkyVersion: ir.milkyVersion,
23871
23924
  packageVersion: ir.milkyPackageVersion,
@@ -23877,16 +23930,6 @@ async function generateJsonSchema(ir, typesModule) {
23877
23930
  }
23878
23931
  //#endregion
23879
23932
  //#region ../common/src/generator/kotlin/kotlinx-serialization.ts
23880
- function toLowerCamelCase$1(s) {
23881
- return s.replace(/_([a-z])/g, (_, c) => c.toUpperCase());
23882
- }
23883
- function toUpperCamelCase$1(s) {
23884
- const lower = toLowerCamelCase$1(s);
23885
- return lower.charAt(0).toUpperCase() + lower.slice(1);
23886
- }
23887
- function indentLines(text, indent = " ") {
23888
- return text.split("\n").map((line) => line.trim() ? indent + line : line).join("\n");
23889
- }
23890
23933
  function escapeString(str) {
23891
23934
  return str.replace(/"/g, "\\\"");
23892
23935
  }
@@ -23897,22 +23940,13 @@ function getKotlinTypeSpec(field, skipDefaultValue = false) {
23897
23940
  else if (field.scalarType === "int64") baseType = "Long";
23898
23941
  else baseType = "Int";
23899
23942
  else if (field.fieldType === "enum") baseType = "String";
23900
- else baseType = toUpperCamelCase$1(field.refStructName);
23943
+ else baseType = snakeCaseToUpperCamelCase(field.refStructName);
23901
23944
  const typeSpec = field.isArray ? `List<${baseType}>` : baseType;
23902
23945
  if (skipDefaultValue) return field.isOptional ? `${typeSpec}?` : typeSpec;
23903
23946
  if (field.defaultValue !== void 0) return `${typeSpec} = ${JSON.stringify(field.defaultValue)}`;
23904
23947
  if (field.isOptional) return `${typeSpec}? = null`;
23905
23948
  return typeSpec;
23906
23949
  }
23907
- function isSameField(f1, f2) {
23908
- if (f1.name !== f2.name) return false;
23909
- if (f1.fieldType !== f2.fieldType) return false;
23910
- if (f1.isArray !== f2.isArray) return false;
23911
- if (f1.isOptional !== f2.isOptional) return false;
23912
- if (f1.fieldType === "scalar" && f2.fieldType === "scalar") return f1.scalarType === f2.scalarType;
23913
- if (f1.fieldType === "ref" && f2.fieldType === "ref") return f1.refStructName === f2.refStructName;
23914
- return true;
23915
- }
23916
23950
  function renderFieldAnnotations(ir, field, l) {
23917
23951
  if (field.fieldType === "ref" && field.isArray) {
23918
23952
  if (field.refStructName === "IncomingSegment") l(" @Serializable(with = TransformUnknownSegmentListSerializer::class)");
@@ -23928,17 +23962,17 @@ function renderIRObject(ir, name, fields, description, includeDesc = true, addit
23928
23962
  l("@Serializable");
23929
23963
  additionalAnnotations.forEach((annotation) => l(annotation));
23930
23964
  if (fields.length > 0) {
23931
- l(`data class ${toUpperCamelCase$1(name)}(`);
23965
+ l(`data class ${snakeCaseToUpperCamelCase(name)}(`);
23932
23966
  fields.forEach((field) => {
23933
23967
  const needsOverride = overrideFields.has(field.name);
23934
23968
  const defaultValue = field.defaultValue !== void 0 ? JSON.stringify(field.defaultValue) : null;
23935
23969
  const overridePrefix = needsOverride ? "override " : "";
23936
23970
  l(` /** ${field.description ?? ""} */`);
23937
23971
  renderFieldAnnotations(ir, field, l);
23938
- l(` @SerialName("${field.name}")${defaultValue ? ` @LiteralDefault("${escapeString(defaultValue)}")` : ""} ${overridePrefix}val ${toLowerCamelCase$1(field.name)}: ${getKotlinTypeSpec(field, needsOverride)},`);
23972
+ l(` @SerialName("${field.name}")${defaultValue ? ` @LiteralDefault("${escapeString(defaultValue)}")` : ""} ${overridePrefix}val ${snakeCaseToLowerCamelCase(field.name)}: ${getKotlinTypeSpec(field, needsOverride)},`);
23939
23973
  });
23940
23974
  l(")");
23941
- } else l(`class ${toUpperCamelCase$1(name)}`);
23975
+ } else l(`class ${snakeCaseToUpperCamelCase(name)}`);
23942
23976
  return lines.join("\n");
23943
23977
  }
23944
23978
  function renderIRUnionStruct$1(ir, struct) {
@@ -23953,28 +23987,22 @@ function renderIRUnionStruct$1(ir, struct) {
23953
23987
  if (struct.description) l(`/** ${struct.description} */`);
23954
23988
  l("@Serializable");
23955
23989
  l(`@JsonClassDiscriminator("${struct.tagFieldName}")`);
23956
- l(`sealed class ${toUpperCamelCase$1(name)} {`);
23990
+ l(`sealed class ${snakeCaseToUpperCamelCase(name)} {`);
23957
23991
  let commonFields = [];
23958
23992
  if (struct.unionType === "withData") commonFields = struct.baseFields || [];
23959
- else if (struct.derivedStructs.length > 0) {
23960
- commonFields = [...struct.derivedStructs[0].fields];
23961
- for (let i = 1; i < struct.derivedStructs.length; i++) {
23962
- const currentStructFields = struct.derivedStructs[i].fields;
23963
- commonFields = commonFields.filter((f1) => currentStructFields.some((f2) => isSameField(f1, f2)));
23964
- }
23965
- }
23993
+ else commonFields = getPlainUnionCommonFields(struct);
23966
23994
  const commonFieldNames = /* @__PURE__ */ new Set();
23967
23995
  if (commonFields.length > 0) {
23968
23996
  commonFields.forEach((field) => {
23969
23997
  commonFieldNames.add(field.name);
23970
23998
  l(` /** ${field.description ?? ""} */`);
23971
- l(` abstract val ${toLowerCamelCase$1(field.name)}: ${getKotlinTypeSpec(field, true)}`);
23999
+ l(` abstract val ${snakeCaseToLowerCamelCase(field.name)}: ${getKotlinTypeSpec(field, true)}`);
23972
24000
  });
23973
24001
  l();
23974
24002
  }
23975
24003
  if (struct.unionType === "withData") struct.derivedTypes.forEach((derivedType, index) => {
23976
- const variantName = toUpperCamelCase$1(derivedType.tagValue);
23977
- const dataTypeName = derivedType.derivingType === "ref" ? toUpperCamelCase$1(derivedType.refStructName) : "Data";
24004
+ const variantName = snakeCaseToUpperCamelCase(derivedType.tagValue);
24005
+ const dataTypeName = derivedType.derivingType === "ref" ? snakeCaseToUpperCamelCase(derivedType.refStructName) : "Data";
23978
24006
  if (derivedType.description) l(` /** ${derivedType.description} */`);
23979
24007
  l(" @Serializable");
23980
24008
  l(` @SerialName("${derivedType.tagValue}")`);
@@ -23982,31 +24010,23 @@ function renderIRUnionStruct$1(ir, struct) {
23982
24010
  struct.baseFields.forEach((field) => {
23983
24011
  l(` /** ${field.description ?? ""} */`);
23984
24012
  renderFieldAnnotations(ir, field, l);
23985
- l(` @SerialName("${field.name}") override val ${toLowerCamelCase$1(field.name)}: ${getKotlinTypeSpec(field, true)},`);
24013
+ l(` @SerialName("${field.name}") override val ${snakeCaseToLowerCamelCase(field.name)}: ${getKotlinTypeSpec(field, true)},`);
23986
24014
  });
23987
24015
  l(` /** 数据字段 */`);
23988
24016
  l(` @SerialName("data") val data: ${dataTypeName}`);
23989
- l(` ) : ${toUpperCamelCase$1(name)}()`);
24017
+ l(` ) : ${snakeCaseToUpperCamelCase(name)}()`);
23990
24018
  const isStruct = derivedType.derivingType === "struct";
23991
24019
  const isRef = derivedType.derivingType === "ref";
23992
24020
  let targetFields = [];
23993
24021
  let targetName = "Data";
23994
24022
  if (isStruct) targetFields = derivedType.fields;
23995
24023
  else if (isRef) {
23996
- targetName = toUpperCamelCase$1(derivedType.refStructName);
24024
+ targetName = snakeCaseToUpperCamelCase(derivedType.refStructName);
23997
24025
  const refStruct = ir.commonStructs.find((s) => s.name === derivedType.refStructName);
23998
24026
  if (refStruct) {
23999
24027
  if (refStruct.structType === "simple") targetFields = refStruct.fields;
24000
- else if (refStruct.structType === "union") {
24001
- if (refStruct.unionType === "withData") targetFields = refStruct.baseFields || [];
24002
- else if (refStruct.derivedStructs && refStruct.derivedStructs.length > 0) {
24003
- targetFields = [...refStruct.derivedStructs[0].fields];
24004
- for (let i = 1; i < refStruct.derivedStructs.length; i++) {
24005
- const currentStructFields = refStruct.derivedStructs[i].fields;
24006
- targetFields = targetFields.filter((f1) => currentStructFields.some((f2) => isSameField(f1, f2)));
24007
- }
24008
- }
24009
- }
24028
+ else if (refStruct.structType === "union") if (refStruct.unionType === "withData") targetFields = refStruct.baseFields || [];
24029
+ else targetFields = getPlainUnionCommonFields(refStruct);
24010
24030
  }
24011
24031
  }
24012
24032
  if (isStruct || targetFields.length > 0) {
@@ -24016,7 +24036,7 @@ function renderIRUnionStruct$1(ir, struct) {
24016
24036
  l();
24017
24037
  }
24018
24038
  targetFields.forEach((field) => {
24019
- const realFieldName = toLowerCamelCase$1(field.name);
24039
+ const realFieldName = snakeCaseToLowerCamelCase(field.name);
24020
24040
  let fieldName = realFieldName;
24021
24041
  const fieldType = getKotlinTypeSpec(field, true);
24022
24042
  if (commonFieldNames.has(field.name)) fieldName = `data${fieldName.charAt(0).toUpperCase() + fieldName.slice(1)}`;
@@ -24032,7 +24052,7 @@ function renderIRUnionStruct$1(ir, struct) {
24032
24052
  });
24033
24053
  else struct.derivedStructs.forEach((derivedStruct, index) => {
24034
24054
  if (derivedStruct.description) l(` /** ${derivedStruct.description} */`);
24035
- l(indentLines(renderIRObject(ir, derivedStruct.tagValue, derivedStruct.fields, "", false, [`@SerialName("${derivedStruct.tagValue}")`], commonFieldNames), " ") + ` : ${toUpperCamelCase$1(name)}()`);
24055
+ l(indentLines(renderIRObject(ir, derivedStruct.tagValue, derivedStruct.fields, "", false, [`@SerialName("${derivedStruct.tagValue}")`], commonFieldNames), " ") + ` : ${snakeCaseToUpperCamelCase(name)}()`);
24036
24056
  if (index !== struct.derivedStructs.length - 1) l();
24037
24057
  });
24038
24058
  l("}");
@@ -24065,75 +24085,71 @@ function generateKotlinxSerializationSpec(ir) {
24065
24085
  l(" explicitNulls = false");
24066
24086
  l("}");
24067
24087
  l();
24068
- l(`
24069
- internal class DropBadElementListSerializer<T>(private val elementSerializer: KSerializer<T>) : KSerializer<List<T>> {
24070
- val listSerializer = ListSerializer(elementSerializer)
24071
-
24072
- override val descriptor: SerialDescriptor =
24073
- listSerializer.descriptor
24074
-
24075
- override fun serialize(encoder: Encoder, value: List<T>) {
24076
- encoder.encodeSerializableValue(listSerializer, value)
24077
- }
24078
-
24079
- override fun deserialize(decoder: Decoder): List<T> {
24080
- if (decoder !is JsonDecoder) {
24081
- throw SerializationException("This serializer can be used only with Json format")
24082
- }
24083
-
24084
- val element = decoder.decodeJsonElement() as? JsonArray
24085
- ?: throw SerializationException("Expected JsonArray for List deserialization")
24086
-
24087
- val out = ArrayList<T>(element.size)
24088
- for (e in element) {
24089
- try {
24090
- out += decoder.json.decodeFromJsonElement(elementSerializer, e)
24091
- } catch (_: SerializationException) {
24092
- // discard bad element quietly
24093
- }
24094
- }
24095
- return out
24096
- }
24097
- }
24098
- `.trim());
24088
+ l("internal class DropBadElementListSerializer<T>(private val elementSerializer: KSerializer<T>) : KSerializer<List<T>> {");
24089
+ l(" val listSerializer = ListSerializer(elementSerializer)");
24099
24090
  l();
24100
- l(`
24101
- internal class TransformUnknownSegmentListSerializer(private val elementSerializer: KSerializer<IncomingSegment>) :
24102
- KSerializer<List<IncomingSegment>> {
24103
-
24104
- val listSerializer = ListSerializer(elementSerializer)
24105
-
24106
- override val descriptor: SerialDescriptor =
24107
- listSerializer.descriptor
24108
-
24109
- override fun serialize(encoder: Encoder, value: List<IncomingSegment>) {
24110
- encoder.encodeSerializableValue(listSerializer, value)
24111
- }
24112
-
24113
- override fun deserialize(decoder: Decoder): List<IncomingSegment> {
24114
- if (decoder !is JsonDecoder) {
24115
- throw SerializationException("This serializer can be used only with Json format")
24116
- }
24117
-
24118
- val element = decoder.decodeJsonElement() as? JsonArray
24119
- ?: throw SerializationException("Expected JsonArray for List deserialization")
24120
-
24121
- val out = ArrayList<IncomingSegment>(element.size)
24122
- for (e in element) {
24123
- out += try {
24124
- decoder.json.decodeFromJsonElement(elementSerializer, e)
24125
- } catch (_: SerializationException) {
24126
- IncomingSegment.Text(
24127
- data = IncomingSegment.Text.Data(
24128
- text = "[\${e.jsonObject["type"]!!.jsonPrimitive.content}]"
24129
- )
24130
- )
24131
- }
24132
- }
24133
- return out
24134
- }
24135
- }
24136
- `.trim());
24091
+ l(" override val descriptor: SerialDescriptor =");
24092
+ l(" listSerializer.descriptor");
24093
+ l();
24094
+ l(" override fun serialize(encoder: Encoder, value: List<T>) {");
24095
+ l(" encoder.encodeSerializableValue(listSerializer, value)");
24096
+ l(" }");
24097
+ l();
24098
+ l(" override fun deserialize(decoder: Decoder): List<T> {");
24099
+ l(" if (decoder !is JsonDecoder) {");
24100
+ l(" throw SerializationException(\"This serializer can be used only with Json format\")");
24101
+ l(" }");
24102
+ l();
24103
+ l(" val element = decoder.decodeJsonElement() as? JsonArray");
24104
+ l(" ?: throw SerializationException(\"Expected JsonArray for List deserialization\")");
24105
+ l();
24106
+ l(" val out = ArrayList<T>(element.size)");
24107
+ l(" for (e in element) {");
24108
+ l(" try {");
24109
+ l(" out += decoder.json.decodeFromJsonElement(elementSerializer, e)");
24110
+ l(" } catch (_: SerializationException) {");
24111
+ l(" // discard bad element quietly");
24112
+ l(" }");
24113
+ l(" }");
24114
+ l(" return out");
24115
+ l(" }");
24116
+ l("}");
24117
+ l();
24118
+ l("internal class TransformUnknownSegmentListSerializer(private val elementSerializer: KSerializer<IncomingSegment>) :");
24119
+ l(" KSerializer<List<IncomingSegment>> {");
24120
+ l();
24121
+ l(" val listSerializer = ListSerializer(elementSerializer)");
24122
+ l();
24123
+ l(" override val descriptor: SerialDescriptor =");
24124
+ l(" listSerializer.descriptor");
24125
+ l();
24126
+ l(" override fun serialize(encoder: Encoder, value: List<IncomingSegment>) {");
24127
+ l(" encoder.encodeSerializableValue(listSerializer, value)");
24128
+ l(" }");
24129
+ l();
24130
+ l(" override fun deserialize(decoder: Decoder): List<IncomingSegment> {");
24131
+ l(" if (decoder !is JsonDecoder) {");
24132
+ l(" throw SerializationException(\"This serializer can be used only with Json format\")");
24133
+ l(" }");
24134
+ l();
24135
+ l(" val element = decoder.decodeJsonElement() as? JsonArray");
24136
+ l(" ?: throw SerializationException(\"Expected JsonArray for List deserialization\")");
24137
+ l();
24138
+ l(" val out = ArrayList<IncomingSegment>(element.size)");
24139
+ l(" for (e in element) {");
24140
+ l(" out += try {");
24141
+ l(" decoder.json.decodeFromJsonElement(elementSerializer, e)");
24142
+ l(" } catch (_: SerializationException) {");
24143
+ l(" IncomingSegment.Text(");
24144
+ l(" data = IncomingSegment.Text.Data(");
24145
+ l(" text = \"[${e.jsonObject[\"type\"]!!.jsonPrimitive.content}]\"");
24146
+ l(" )");
24147
+ l(" )");
24148
+ l(" }");
24149
+ l(" }");
24150
+ l(" return out");
24151
+ l(" }");
24152
+ l("}");
24137
24153
  l();
24138
24154
  l("// ####################################");
24139
24155
  l("// Common Structs");
@@ -24163,11 +24179,11 @@ internal class TransformUnknownSegmentListSerializer(private val elementSerializ
24163
24179
  l(`// ---- ${category.name} ----`);
24164
24180
  l();
24165
24181
  category.apis.forEach((api) => {
24166
- if (api.requestFields && api.requestFields.length > 0) l(renderIRObject(ir, `${toUpperCamelCase$1(api.endpoint)}Input`, api.requestFields, "", false));
24167
- else l(`typealias ${toUpperCamelCase$1(api.endpoint)}Input = ApiEmptyStruct`);
24182
+ if (api.requestFields && api.requestFields.length > 0) l(renderIRObject(ir, `${snakeCaseToUpperCamelCase(api.endpoint)}Input`, api.requestFields, "", false));
24183
+ else l(`typealias ${snakeCaseToUpperCamelCase(api.endpoint)}Input = ApiEmptyStruct`);
24168
24184
  l();
24169
- if (api.responseFields) l(renderIRObject(ir, `${toUpperCamelCase$1(api.endpoint)}Output`, api.responseFields, "", false));
24170
- else l(`typealias ${toUpperCamelCase$1(api.endpoint)}Output = ApiEmptyStruct`);
24185
+ if (api.responseFields) l(renderIRObject(ir, `${snakeCaseToUpperCamelCase(api.endpoint)}Output`, api.responseFields, "", false));
24186
+ else l(`typealias ${snakeCaseToUpperCamelCase(api.endpoint)}Output = ApiEmptyStruct`);
24171
24187
  l();
24172
24188
  });
24173
24189
  });
@@ -24179,7 +24195,7 @@ internal class TransformUnknownSegmentListSerializer(private val elementSerializ
24179
24195
  ir.apiCategories.forEach((category) => {
24180
24196
  category.apis.forEach((api) => {
24181
24197
  l(` /** ${api.description} */`);
24182
- l(` object ${toUpperCamelCase$1(api.endpoint)} : ApiEndpoint<${toUpperCamelCase$1(api.endpoint)}Input, ${toUpperCamelCase$1(api.endpoint)}Output>("/${api.endpoint}")`);
24198
+ l(` object ${snakeCaseToUpperCamelCase(api.endpoint)} : ApiEndpoint<${snakeCaseToUpperCamelCase(api.endpoint)}Input, ${snakeCaseToUpperCamelCase(api.endpoint)}Output>("/${api.endpoint}")`);
24183
24199
  });
24184
24200
  });
24185
24201
  l("}");
@@ -24244,14 +24260,6 @@ function generateMarkdownRoadmap(ir) {
24244
24260
  }
24245
24261
  //#endregion
24246
24262
  //#region ../common/src/generator/openapi/index.ts
24247
- const preserveFullCapitalizedWords = ["csrf"];
24248
- function snakeCaseToPascalCase(snakeCase) {
24249
- return snakeCase.split("_").map((part) => preserveFullCapitalizedWords.includes(part) ? part.toUpperCase() : part.charAt(0).toUpperCase() + part.slice(1)).join("");
24250
- }
24251
- function sanitizeSchema(schema) {
24252
- const { $schema, ...rest } = schema;
24253
- return rest;
24254
- }
24255
24263
  function buildComponents() {
24256
24264
  const jsonSchemas = toJSONSchema(globalRegistry, {
24257
24265
  metadata: globalRegistry,
@@ -24259,7 +24267,7 @@ function buildComponents() {
24259
24267
  target: "openapi-3.0",
24260
24268
  uri: (id) => `#/components/schemas/${id}`
24261
24269
  }).schemas;
24262
- const schemas = Object.fromEntries(Object.entries(jsonSchemas ?? {}).map(([name, schema]) => [name, sanitizeSchema(schema)]));
24270
+ const schemas = Object.fromEntries(Object.entries(jsonSchemas ?? {}).map(([name, schema]) => [name, sanitizeGeneratedSchema(schema)]));
24263
24271
  schemas.ApiResponse = {
24264
24272
  type: "object",
24265
24273
  required: ["status", "retcode"],
@@ -24291,8 +24299,9 @@ function buildPaths(ir) {
24291
24299
  const paths = {};
24292
24300
  ir.apiCategories.forEach((category) => {
24293
24301
  category.apis.forEach((spec) => {
24294
- const requestIdOrNull = spec.requestFields && `${snakeCaseToPascalCase(spec.endpoint)}Input`;
24295
- const responseIdOrNull = spec.responseFields && `${snakeCaseToPascalCase(spec.endpoint)}Output`;
24302
+ const typeNames = getApiTypeNames(spec.endpoint);
24303
+ const requestIdOrNull = spec.requestFields && typeNames.inputName;
24304
+ const responseIdOrNull = spec.responseFields && typeNames.outputName;
24296
24305
  paths[`/api/${spec.endpoint}`] = { post: {
24297
24306
  tags: [category.name],
24298
24307
  summary: spec.description,
@@ -24324,12 +24333,8 @@ function buildWebhooks() {
24324
24333
  responses: { "200": { description: "已成功接收事件" } }
24325
24334
  } } };
24326
24335
  }
24327
- async function initTypesModule(ir) {
24328
- const { code } = (0, import_dist.transform)(generateTypeScriptZodSpec(ir), { transforms: ["typescript"] });
24329
- return await importCodeAsModule(code.replace("'zod'", `'${import.meta.resolve("zod")}'`));
24330
- }
24331
24336
  async function generateOpenApiSpec(ir, typesModule) {
24332
- initRegistry(ir, typesModule ?? await initTypesModule(ir));
24337
+ initializeZodRegistry(ir, typesModule ?? await loadGeneratedZodTypesModule(ir));
24333
24338
  return {
24334
24339
  openapi: "3.1.0",
24335
24340
  info: {
@@ -24357,19 +24362,9 @@ async function generateOpenApiSpec(ir, typesModule) {
24357
24362
  }
24358
24363
  //#endregion
24359
24364
  //#region ../common/src/generator/rust/serde.ts
24360
- function toLowerCamelCase(s) {
24361
- return s.replace(/_([a-z])/g, (_, c) => c.toUpperCase());
24362
- }
24363
- function toUpperCamelCase(s) {
24364
- const lower = toLowerCamelCase(s);
24365
- return lower.charAt(0).toUpperCase() + lower.slice(1);
24366
- }
24367
24365
  function toSnakeCase(s) {
24368
24366
  return s.replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/-/g, "_").toLowerCase();
24369
24367
  }
24370
- function formatDocComment(text, indent = "") {
24371
- return text.split("\n").map((line) => line.trim()).filter((line) => line.length > 0).map((line) => `${indent}/// ${line}`);
24372
- }
24373
24368
  function escapeRustString(str) {
24374
24369
  let out = "\"";
24375
24370
  for (const ch of str) switch (ch) {
@@ -24416,7 +24411,7 @@ function getRustBaseType(field) {
24416
24411
  return "i32";
24417
24412
  }
24418
24413
  if (field.fieldType === "enum") return "String";
24419
- return toUpperCamelCase(field.refStructName);
24414
+ return snakeCaseToUpperCamelCase(field.refStructName);
24420
24415
  }
24421
24416
  function getRustTypeSpec(field) {
24422
24417
  const baseType = getRustBaseType(field);
@@ -24480,40 +24475,6 @@ const rustKeywords = new Set([
24480
24475
  function toRustFieldName(name) {
24481
24476
  return rustKeywords.has(name) ? `r#${name}` : name;
24482
24477
  }
24483
- function collectUnionStructNames(ir) {
24484
- return new Set(ir.commonStructs.filter((struct) => struct.structType === "union").map((struct) => struct.name));
24485
- }
24486
- function collectArrayUnionRefs(ir, unionStructNames) {
24487
- const arrayUnionRefs = /* @__PURE__ */ new Set();
24488
- const handleFields = (fields) => {
24489
- fields.forEach((field) => {
24490
- if (field.fieldType === "ref" && field.isArray && unionStructNames.has(field.refStructName)) arrayUnionRefs.add(field.refStructName);
24491
- });
24492
- };
24493
- ir.commonStructs.forEach((struct) => {
24494
- if (struct.structType === "simple") {
24495
- handleFields(struct.fields);
24496
- return;
24497
- }
24498
- if (struct.unionType === "withData") {
24499
- handleFields(struct.baseFields);
24500
- struct.derivedTypes.forEach((derivedType) => {
24501
- if (derivedType.derivingType === "struct") handleFields(derivedType.fields);
24502
- });
24503
- return;
24504
- }
24505
- struct.derivedStructs.forEach((derivedStruct) => {
24506
- handleFields(derivedStruct.fields);
24507
- });
24508
- });
24509
- ir.apiCategories.forEach((category) => {
24510
- category.apis.forEach((api) => {
24511
- if (api.requestFields) handleFields(api.requestFields);
24512
- if (api.responseFields) handleFields(api.responseFields);
24513
- });
24514
- });
24515
- return arrayUnionRefs;
24516
- }
24517
24478
  function getArrayUnionDeserializeFn(field, unionStructNames) {
24518
24479
  if (field.fieldType !== "ref" || !field.isArray || field.defaultValue !== void 0) return null;
24519
24480
  const fnPrefix = field.isOptional ? "deserialize_optional_" : "deserialize_";
@@ -24522,7 +24483,7 @@ function getArrayUnionDeserializeFn(field, unionStructNames) {
24522
24483
  return null;
24523
24484
  }
24524
24485
  function renderDropBadElementListHelpers(typeName) {
24525
- const rustTypeName = toUpperCamelCase(typeName);
24486
+ const rustTypeName = snakeCaseToUpperCamelCase(typeName);
24526
24487
  const snakeTypeName = toSnakeCase(typeName);
24527
24488
  return [
24528
24489
  `fn deserialize_drop_bad_${snakeTypeName}_list<'de, D>(deserializer: D) -> Result<Vec<${rustTypeName}>, D::Error>`,
@@ -24616,7 +24577,7 @@ function ensureDefaultHelpers(ctx, helperParts, fieldType, defaultValue) {
24616
24577
  function renderFieldLines(field, ctx, helperParts, indent = " ", typeOverride, isPublic = true) {
24617
24578
  const lines = [];
24618
24579
  const rustFieldType = typeOverride ?? getRustTypeSpec(field);
24619
- if (field.description) lines.push(...formatDocComment(field.description, indent));
24580
+ if (field.description) lines.push(...formatDocComment(field.description, `${indent}/// `));
24620
24581
  const serdeArgs = [`rename = ${escapeRustString(field.name)}`];
24621
24582
  const arrayUnionDeserializeFn = getArrayUnionDeserializeFn(field, ctx.unionStructNames);
24622
24583
  if (field.defaultValue !== void 0) {
@@ -24632,7 +24593,7 @@ function renderFieldLines(field, ctx, helperParts, indent = " ", typeOverride
24632
24593
  return lines;
24633
24594
  }
24634
24595
  function renderIRSimpleStruct(name, fields, description, ctx) {
24635
- const structName = toUpperCamelCase(name);
24596
+ const structName = snakeCaseToUpperCamelCase(name);
24636
24597
  const lines = [];
24637
24598
  if (description) lines.push(...formatDocComment(description));
24638
24599
  lines.push("#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]");
@@ -24654,7 +24615,7 @@ function renderTypeAlias(name, target, description) {
24654
24615
  return lines.join("\n");
24655
24616
  }
24656
24617
  function renderIRUnionStruct(struct, ctx) {
24657
- const enumName = toUpperCamelCase(struct.name);
24618
+ const enumName = snakeCaseToUpperCamelCase(struct.name);
24658
24619
  const lines = [];
24659
24620
  const extraDefs = [];
24660
24621
  if (struct.description) lines.push(...formatDocComment(struct.description));
@@ -24662,10 +24623,10 @@ function renderIRUnionStruct(struct, ctx) {
24662
24623
  lines.push(`#[serde(tag = ${escapeRustString(struct.tagFieldName)})]`);
24663
24624
  lines.push(`pub enum ${enumName} {`);
24664
24625
  if (struct.unionType === "withData") struct.derivedTypes.forEach((derivedType, index) => {
24665
- const variantName = toUpperCamelCase(derivedType.tagValue);
24666
- const dataTypeName = derivedType.derivingType === "ref" ? toUpperCamelCase(derivedType.refStructName) : `${enumName}${toUpperCamelCase(derivedType.tagValue)}Data`;
24626
+ const variantName = snakeCaseToUpperCamelCase(derivedType.tagValue);
24627
+ const dataTypeName = derivedType.derivingType === "ref" ? snakeCaseToUpperCamelCase(derivedType.refStructName) : `${enumName}${snakeCaseToUpperCamelCase(derivedType.tagValue)}Data`;
24667
24628
  const dataFieldDescription = derivedType.description ? `${derivedType.description}数据` : "数据字段";
24668
- if (derivedType.description) lines.push(...formatDocComment(derivedType.description, " "));
24629
+ if (derivedType.description) lines.push(...formatDocComment(derivedType.description, " /// "));
24669
24630
  lines.push(` #[serde(rename = ${escapeRustString(derivedType.tagValue)})]`);
24670
24631
  lines.push(` ${variantName} {`);
24671
24632
  struct.baseFields.forEach((field) => {
@@ -24692,8 +24653,8 @@ function renderIRUnionStruct(struct, ctx) {
24692
24653
  if (index !== struct.derivedTypes.length - 1) lines.push("");
24693
24654
  });
24694
24655
  else struct.derivedStructs.forEach((derivedStruct, index) => {
24695
- const variantName = toUpperCamelCase(derivedStruct.tagValue);
24696
- if (derivedStruct.description) lines.push(...formatDocComment(derivedStruct.description, " "));
24656
+ const variantName = snakeCaseToUpperCamelCase(derivedStruct.tagValue);
24657
+ if (derivedStruct.description) lines.push(...formatDocComment(derivedStruct.description, " /// "));
24697
24658
  lines.push(` #[serde(rename = ${escapeRustString(derivedStruct.tagValue)})]`);
24698
24659
  if (derivedStruct.fields.length === 0) lines.push(` ${variantName},`);
24699
24660
  else {
@@ -24777,12 +24738,12 @@ function generateRustSerdeSpec(ir) {
24777
24738
  l(`// ---- ${category.name} ----`);
24778
24739
  l();
24779
24740
  category.apis.forEach((api) => {
24780
- const inputName = `${toUpperCamelCase(api.endpoint)}Input`;
24741
+ const inputName = `${snakeCaseToUpperCamelCase(api.endpoint)}Input`;
24781
24742
  const inputDescription = `${api.description} API 请求参数`;
24782
24743
  if (api.requestFields && api.requestFields.length > 0) l(renderIRSimpleStruct(inputName, api.requestFields, inputDescription, ctx));
24783
24744
  else l(renderTypeAlias(inputName, "ApiEmptyStruct", inputDescription));
24784
24745
  l();
24785
- const outputName = `${toUpperCamelCase(api.endpoint)}Output`;
24746
+ const outputName = `${snakeCaseToUpperCamelCase(api.endpoint)}Output`;
24786
24747
  const outputDescription = `${api.description} API 响应数据`;
24787
24748
  if (api.responseFields && api.responseFields.length > 0) l(renderIRSimpleStruct(outputName, api.responseFields, outputDescription, ctx));
24788
24749
  else l(renderTypeAlias(outputName, "ApiEmptyStruct", outputDescription));
@@ -24865,7 +24826,7 @@ function generateRustSerdeSpec(ir) {
24865
24826
  l();
24866
24827
  ir.apiCategories.forEach((category) => {
24867
24828
  category.apis.forEach((api) => {
24868
- const endpointName = toUpperCamelCase(api.endpoint);
24829
+ const endpointName = snakeCaseToUpperCamelCase(api.endpoint);
24869
24830
  l(`/// ${api.description}`);
24870
24831
  l("#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]");
24871
24832
  l(`pub struct ${endpointName};`);
@@ -24882,21 +24843,13 @@ function generateRustSerdeSpec(ir) {
24882
24843
  }
24883
24844
  //#endregion
24884
24845
  //#region ../common/src/generator/typescript/static.ts
24885
- function useLines() {
24886
- const lines = [];
24887
- function l(line = "") {
24888
- lines.push(line);
24889
- }
24890
- return [lines, l];
24891
- }
24892
24846
  function generateTypeScriptStaticSpec(ir) {
24893
- const [lines, l] = useLines();
24847
+ const writer = createLineWriter();
24848
+ const l = writer.line;
24894
24849
  l(`// Generated from Milky ${ir.milkyVersion} (${ir.milkyPackageVersion})`);
24895
24850
  l();
24896
- l(`
24897
- export const milkyVersion = '${ir.milkyVersion}';
24898
- export const milkyPackageVersion = '${ir.milkyPackageVersion}';
24899
- `.trim());
24851
+ l(`export const milkyVersion = '${ir.milkyVersion}';`);
24852
+ l(`export const milkyPackageVersion = '${ir.milkyPackageVersion}';`);
24900
24853
  l();
24901
24854
  l("// ####################################");
24902
24855
  l("// Common Structs");
@@ -24950,7 +24903,7 @@ export const milkyPackageVersion = '${ir.milkyPackageVersion}';
24950
24903
  l(`export type ${struct.name} =`);
24951
24904
  struct.derivedTypes.forEach((derivedType, index) => {
24952
24905
  l(" | {");
24953
- l(` type: '${derivedType.tagValue}';`);
24906
+ l(` ${struct.tagFieldName}: '${derivedType.tagValue}';`);
24954
24907
  l(` data: ${normalizeDerivedStructName(struct.name, derivedType.tagValue)}Data;`);
24955
24908
  l(` }${index === struct.derivedTypes.length - 1 ? ";" : ""}`);
24956
24909
  });
@@ -24963,29 +24916,30 @@ export const milkyPackageVersion = '${ir.milkyPackageVersion}';
24963
24916
  l();
24964
24917
  ir.apiCategories.forEach((category) => {
24965
24918
  category.apis.forEach((api) => {
24919
+ const typeNames = getApiTypeNames(api.endpoint);
24966
24920
  l(`/** ${api.description} API 请求参数 */`);
24967
24921
  if (api.requestFields !== void 0) {
24968
- l(`export interface ${snakeCaseToPascalCase$2(api.endpoint)}Request {`);
24922
+ l(`export interface ${typeNames.requestName} {`);
24969
24923
  api.requestFields.forEach((field) => {
24970
24924
  l(` /** ${field.description} */`);
24971
24925
  l(` ${field.name}${field.isOptional ? "?" : ""}: ${getTypeScriptTypeProjection(field)};`);
24972
24926
  });
24973
24927
  l("}");
24974
- } else l(`export type ${snakeCaseToPascalCase$2(api.endpoint)}Request = {};`);
24928
+ } else l(`export type ${typeNames.requestName} = {};`);
24975
24929
  l();
24976
24930
  l(`/** ${api.description} API 响应数据 */`);
24977
24931
  if (api.responseFields !== void 0) {
24978
- l(`export interface ${snakeCaseToPascalCase$2(api.endpoint)}Response {`);
24932
+ l(`export interface ${typeNames.responseName} {`);
24979
24933
  api.responseFields.forEach((field) => {
24980
24934
  l(` /** ${field.description} */`);
24981
24935
  l(` ${field.name}${field.isOptional ? "?" : ""}: ${getTypeScriptTypeProjection(field)};`);
24982
24936
  });
24983
24937
  l("}");
24984
- } else l(`export type ${snakeCaseToPascalCase$2(api.endpoint)}Response = {};`);
24938
+ } else l(`export type ${typeNames.responseName} = {};`);
24985
24939
  l();
24986
24940
  });
24987
24941
  });
24988
- return lines.join("\n");
24942
+ return writer.toString();
24989
24943
  }
24990
24944
  //#endregion
24991
24945
  //#region ../protocol/src/builder.ts