(
className: string,
schema: JSONSchema7,
visibility: "public" | "internal",
extraClasses: string[]
)
| 1614 | } |
| 1615 | |
| 1616 | function emitRpcClass( |
| 1617 | className: string, |
| 1618 | schema: JSONSchema7, |
| 1619 | visibility: "public" | "internal", |
| 1620 | extraClasses: string[] |
| 1621 | ): string { |
| 1622 | const effectiveSchema = |
| 1623 | resolveObjectSchema(schema, rpcDefinitions) ?? |
| 1624 | resolveSchema(schema, rpcDefinitions) ?? |
| 1625 | schema; |
| 1626 | // Visibility is driven by the JSON Schema definition itself (set via |
| 1627 | // `.asInternal()` on the originating Zod schema). The runtime schema |
| 1628 | // generator enforces that no public method references an internal type, |
| 1629 | // so it's safe to upgrade callers' default to internal here. |
| 1630 | if ( |
| 1631 | (schema as Record<string, unknown>).visibility === "internal" || |
| 1632 | (effectiveSchema as Record<string, unknown>).visibility === "internal" |
| 1633 | ) { |
| 1634 | visibility = "internal"; |
| 1635 | } |
| 1636 | const schemaKey = stableStringify(effectiveSchema); |
| 1637 | const existingSchema = emittedRpcClassSchemas.get(className); |
| 1638 | if (existingSchema) { |
| 1639 | if (existingSchema !== schemaKey) { |
| 1640 | throw new Error( |
| 1641 | `Conflicting RPC class name "${className}" for different schemas. Add a schema title/withTypeName to disambiguate.` |
| 1642 | ); |
| 1643 | } |
| 1644 | return ""; |
| 1645 | } |
| 1646 | |
| 1647 | emittedRpcClassSchemas.set(className, schemaKey); |
| 1648 | |
| 1649 | const requiredSet = new Set(effectiveSchema.required || []); |
| 1650 | const lines: string[] = []; |
| 1651 | lines.push(...xmlDocComment(schema.description || effectiveSchema.description || `RPC data type for ${className.replace(/(Request|Result|Params)$/, "")} operations.`, "")); |
| 1652 | if (experimentalRpcTypes.has(className) || isSchemaExperimental(schema) || isSchemaExperimental(effectiveSchema)) { |
| 1653 | pushExperimentalAttribute(lines); |
| 1654 | } |
| 1655 | if (isSchemaDeprecated(schema) || isSchemaDeprecated(effectiveSchema)) { |
| 1656 | pushObsoleteAttributes(lines); |
| 1657 | } |
| 1658 | lines.push(`${visibility} sealed class ${className}`, `{`); |
| 1659 | |
| 1660 | const props = Object.entries(effectiveSchema.properties || {}).sort(([a], [b]) => a.localeCompare(b)); |
| 1661 | for (let i = 0; i < props.length; i++) { |
| 1662 | const [propName, propSchema] = props[i]; |
| 1663 | if (typeof propSchema !== "object") continue; |
| 1664 | const prop = propSchema as JSONSchema7; |
| 1665 | const isReq = requiredSet.has(propName); |
| 1666 | const csharpName = toCSharpPropertyName(propName, prop); |
| 1667 | const csharpType = resolveRpcType(prop, isReq, className, csharpName, extraClasses); |
| 1668 | |
| 1669 | lines.push(...xmlDocPropertyComment(prop.description, propName, " ")); |
| 1670 | lines.push(...emitDataAnnotations(prop, " ", csharpType)); |
| 1671 | if (isSchemaDeprecated(prop)) pushObsoleteAttributes(lines, " "); |
| 1672 | if (isSchemaExperimental(prop)) pushExperimentalAttribute(lines, " "); |
| 1673 | if (isMillisecondsDurationProperty(propName, prop)) lines.push(` [JsonConverter(typeof(MillisecondsTimeSpanConverter))]`); |
no test coverage detected
searching dependent graphs…