@globalart/zod-to-proto 1.0.19 → 2.0.0
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/dist/index.d.mts +4 -39
- package/dist/index.mjs +4 -26
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -17
- package/dist/index.cjs +0 -549
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -70
package/dist/index.d.mts
CHANGED
|
@@ -1,12 +1,7 @@
|
|
|
1
|
-
import { ZodObject
|
|
1
|
+
import { ZodObject } from "zod";
|
|
2
2
|
|
|
3
3
|
//#region src/types.d.ts
|
|
4
4
|
|
|
5
|
-
/**
|
|
6
|
-
* Input type for service definitions.
|
|
7
|
-
* Can be either an array of service definitions or an object mapping service names to Zod schemas.
|
|
8
|
-
*/
|
|
9
|
-
type ServicesInput = ServiceDefinition[] | Record<string, ZodObject<any>>;
|
|
10
5
|
/**
|
|
11
6
|
* Options for converting Zod schemas to protobuf definitions.
|
|
12
7
|
*/
|
|
@@ -20,42 +15,12 @@ interface ZodToProtobufOptions {
|
|
|
20
15
|
/** Prefix to add to all generated type names */
|
|
21
16
|
typePrefix?: string;
|
|
22
17
|
/** Service definitions to include in the protobuf output */
|
|
23
|
-
services?:
|
|
18
|
+
services?: any;
|
|
24
19
|
/** Whether to skip generating the root message */
|
|
25
20
|
skipRootMessage?: boolean;
|
|
26
21
|
}
|
|
27
|
-
/**
|
|
28
|
-
* Definition of a single service method.
|
|
29
|
-
*/
|
|
30
|
-
interface ServiceMethod {
|
|
31
|
-
/** Method name */
|
|
32
|
-
name: string;
|
|
33
|
-
/** Zod schema for the request message */
|
|
34
|
-
request: ZodTypeAny;
|
|
35
|
-
/** Zod schema for the response message */
|
|
36
|
-
response: ZodTypeAny;
|
|
37
|
-
/** Streaming type: "client" for client streaming, "server" for server streaming, "bidirectional" for both */
|
|
38
|
-
streaming?: "client" | "server" | "bidirectional";
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Definition of a protobuf service containing multiple methods.
|
|
42
|
-
*/
|
|
43
|
-
interface ServiceDefinition {
|
|
44
|
-
/** Service name */
|
|
45
|
-
name: string;
|
|
46
|
-
/** Array of service methods */
|
|
47
|
-
methods: ServiceMethod[];
|
|
48
|
-
}
|
|
49
22
|
//#endregion
|
|
50
23
|
//#region src/zod-to-protobuf.d.ts
|
|
51
|
-
/**
|
|
52
|
-
* Generates a protobuf definition string for services only (without root message).
|
|
53
|
-
* Convenience function that calls zodToProtobuf with an empty schema.
|
|
54
|
-
*
|
|
55
|
-
* @param options - Options for protobuf generation
|
|
56
|
-
* @returns Protobuf definition string
|
|
57
|
-
*/
|
|
58
|
-
declare const zodToProtobufService: (options?: ZodToProtobufOptions) => string;
|
|
59
24
|
/**
|
|
60
25
|
* Converts a Zod schema to a protobuf definition string.
|
|
61
26
|
* Generates messages, enums, and services based on the provided schema and options.
|
|
@@ -64,7 +29,7 @@ declare const zodToProtobufService: (options?: ZodToProtobufOptions) => string;
|
|
|
64
29
|
* @param options - Options for protobuf generation including package name, root message name, type prefix, and services
|
|
65
30
|
* @returns Complete protobuf definition string
|
|
66
31
|
*/
|
|
67
|
-
declare const
|
|
32
|
+
declare const zodToProtobufService: (options?: ZodToProtobufOptions) => string;
|
|
68
33
|
//#endregion
|
|
69
|
-
export {
|
|
34
|
+
export { zodToProtobufService };
|
|
70
35
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import * as inflection from "inflection";
|
|
2
1
|
import { ZodArray, ZodBigInt, ZodBoolean, ZodDate, ZodEnum, ZodMap, ZodNullable, ZodNumber, ZodObject, ZodOptional, ZodRecord, ZodSet, ZodString, ZodTuple, ZodType, z } from "zod";
|
|
2
|
+
import * as inflection from "inflection";
|
|
3
3
|
|
|
4
4
|
//#region src/utils.ts
|
|
5
5
|
/**
|
|
@@ -456,16 +456,6 @@ const generateServices = (services, context) => {
|
|
|
456
456
|
//#endregion
|
|
457
457
|
//#region src/zod-to-protobuf.ts
|
|
458
458
|
/**
|
|
459
|
-
* Generates a protobuf definition string for services only (without root message).
|
|
460
|
-
* Convenience function that calls zodToProtobuf with an empty schema.
|
|
461
|
-
*
|
|
462
|
-
* @param options - Options for protobuf generation
|
|
463
|
-
* @returns Protobuf definition string
|
|
464
|
-
*/
|
|
465
|
-
const zodToProtobufService = (options = {}) => {
|
|
466
|
-
return zodToProtobuf(z.object(), options);
|
|
467
|
-
};
|
|
468
|
-
/**
|
|
469
459
|
* Converts a Zod schema to a protobuf definition string.
|
|
470
460
|
* Generates messages, enums, and services based on the provided schema and options.
|
|
471
461
|
*
|
|
@@ -473,22 +463,10 @@ const zodToProtobufService = (options = {}) => {
|
|
|
473
463
|
* @param options - Options for protobuf generation including package name, root message name, type prefix, and services
|
|
474
464
|
* @returns Complete protobuf definition string
|
|
475
465
|
*/
|
|
476
|
-
const
|
|
477
|
-
const { packageName = "default",
|
|
466
|
+
const zodToProtobufService = (options = {}) => {
|
|
467
|
+
const { packageName = "default", typePrefix = "", services } = options;
|
|
478
468
|
const messages = /* @__PURE__ */ new Map();
|
|
479
469
|
const enums = /* @__PURE__ */ new Map();
|
|
480
|
-
if (schema && !skipRootMessage) {
|
|
481
|
-
const fields = traverseSchema({
|
|
482
|
-
schema,
|
|
483
|
-
messages,
|
|
484
|
-
enums,
|
|
485
|
-
typePrefix
|
|
486
|
-
});
|
|
487
|
-
if (fields.length > 0) {
|
|
488
|
-
const rootMessageKey = `${typePrefix}${rootMessageName}`;
|
|
489
|
-
messages.set(rootMessageKey, fields);
|
|
490
|
-
}
|
|
491
|
-
}
|
|
492
470
|
const context = {
|
|
493
471
|
messages,
|
|
494
472
|
enums,
|
|
@@ -516,5 +494,5 @@ ${content}
|
|
|
516
494
|
};
|
|
517
495
|
|
|
518
496
|
//#endregion
|
|
519
|
-
export {
|
|
497
|
+
export { zodToProtobufService };
|
|
520
498
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["tupleFields: ProtobufField[]","methods: ServiceMethod[]","streaming: \"client\" | \"server\" | \"bidirectional\" | undefined","protoDefinition: string"],"sources":["../src/utils.ts","../src/traversers.ts","../src/service-generator.ts","../src/zod-to-protobuf.ts"],"sourcesContent":["import { ZodNumber } from \"zod\";\nimport type { ProtobufField } from \"./types\";\n\n/**\n * Determines the protobuf number type name based on Zod number schema.\n * Returns \"int32\" for integers, \"double\" for floating point numbers.\n *\n * @param value - Zod number schema\n * @returns Protobuf number type name (\"int32\" or \"double\")\n */\nexport const getNumberTypeName = ({ value }: { value: ZodNumber }): string => {\n return value.isInt ? \"int32\" : \"double\";\n};\n\n/**\n * Converts a string to PascalCase format.\n * Handles dot-separated strings by capitalizing each part.\n *\n * @param value - String to convert\n * @returns PascalCase string\n */\nexport const toPascalCase = ({ value }: { value: string }): string => {\n return value\n .split(\".\")\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join(\"\");\n};\n\n/**\n * Converts a protobuf field definition to its type string representation.\n * Filters out null/empty values and joins the remaining types.\n *\n * @param field - Protobuf field definition\n * @returns Type string for the protobuf field\n */\nexport const protobufFieldToType = ({\n field,\n}: {\n field: ProtobufField;\n}): string => {\n return field.types.filter(Boolean).join(\" \");\n};\n","import * as inflection from \"inflection\";\nimport {\n ZodArray,\n ZodBigInt,\n ZodBoolean,\n ZodDate,\n ZodEnum,\n ZodMap,\n ZodNullable,\n ZodNumber,\n ZodObject,\n ZodOptional,\n ZodRecord,\n ZodSet,\n ZodString,\n ZodTuple,\n ZodType,\n type ZodTypeAny,\n} from \"zod\";\nimport {\n ZodArrayDefinition,\n ZodMapDefinition,\n ZodRecordDefinition,\n type ProtobufField,\n} from \"./types\";\nimport { getNumberTypeName, toPascalCase, protobufFieldToType } from \"./utils\";\n\n/**\n * Traverses a Zod array or set schema and converts it to protobuf repeated fields.\n * Handles nested types and generates appropriate field definitions.\n *\n * @param key - Field name\n * @param value - Zod array or set schema\n * @param messages - Map of message names to their protobuf fields\n * @param enums - Map of enum names to their protobuf values\n * @param typePrefix - Optional prefix for type names\n * @param parentKey - Optional parent message name for nested types\n * @returns Array of protobuf field definitions\n */\nexport const traverseArray = ({\n key,\n value,\n messages,\n enums,\n typePrefix,\n parentKey,\n}: {\n key: string;\n value: ZodArray<ZodTypeAny> | ZodSet<ZodTypeAny>;\n messages: Map<string, string[]>;\n enums: Map<string, string[]>;\n typePrefix: string | null;\n parentKey?: string;\n}): ProtobufField[] => {\n const nestedValue =\n value instanceof ZodArray\n ? value.element\n : value instanceof ZodSet\n ? (value.def as unknown as ZodArrayDefinition).valueType\n : // @ts-expect-error\n (value.def as unknown as ZodArrayDefinition).element;\n\n const singularKey = inflection.singularize(key);\n const elementFields = traverseKey({\n key: singularKey,\n value: nestedValue,\n messages,\n enums,\n isOptional: false,\n isInArray: true,\n typePrefix,\n parentKey: nestedValue instanceof ZodObject ? parentKey : undefined,\n });\n return elementFields.map((field) => ({\n ...field,\n types: [\"repeated\", ...field.types],\n name: field.name.replace(singularKey, key),\n }));\n};\n\n/**\n * Traverses a Zod map schema and converts it to a protobuf map type.\n * Validates that both key and value types are simple types suitable for map keys/values.\n *\n * @param key - Field name\n * @param value - Zod map schema\n * @param messages - Map of message names to their protobuf fields\n * @param enums - Map of enum names to their protobuf values\n * @param typePrefix - Optional prefix for type names\n * @param parentKey - Optional parent message name for nested types\n * @returns Array containing a single protobuf map field definition, or empty array if invalid\n */\nexport const traverseMap = ({\n key,\n value,\n messages,\n enums,\n typePrefix,\n parentKey,\n}: {\n key: string;\n value: ZodMap<ZodTypeAny, ZodTypeAny>;\n messages: Map<string, string[]>;\n enums: Map<string, string[]>;\n typePrefix: string | null;\n parentKey?: string;\n}): ProtobufField[] => {\n const mapDef = value.def as ZodMapDefinition;\n\n const keyType = traverseKey({\n key: inflection.singularize(key),\n value: mapDef.keyType,\n messages,\n enums,\n isOptional: false,\n isInArray: true,\n typePrefix,\n parentKey,\n });\n const valueType = traverseKey({\n key: inflection.singularize(key),\n value: mapDef.valueType,\n messages,\n enums,\n isOptional: false,\n isInArray: true,\n typePrefix,\n parentKey,\n });\n\n if (!keyType[0] || keyType.length !== 1) {\n return [];\n }\n\n if (!valueType[0] || valueType.length !== 1) {\n return [];\n }\n\n const mapType = `map<${protobufFieldToType({ field: keyType[0] })}, ${protobufFieldToType({ field: valueType[0] })}>`;\n return [\n {\n types: [mapType],\n name: key,\n },\n ];\n};\n\n/**\n * Traverses a Zod record schema and converts it to a protobuf map type.\n * Similar to traverseMap but handles ZodRecord type.\n *\n * @param key - Field name\n * @param value - Zod record schema\n * @param messages - Map of message names to their protobuf fields\n * @param enums - Map of enum names to their protobuf values\n * @param typePrefix - Optional prefix for type names\n * @param parentKey - Optional parent message name for nested types\n * @returns Array containing a single protobuf map field definition, or empty array if invalid\n */\nexport const traverseRecord = ({\n key,\n value,\n messages,\n enums,\n typePrefix,\n parentKey,\n}: {\n key: string;\n value: ZodRecord;\n messages: Map<string, string[]>;\n enums: Map<string, string[]>;\n typePrefix: string | null;\n parentKey?: string;\n}): ProtobufField[] => {\n const recordDef = value.def as unknown as ZodRecordDefinition;\n\n const keyType = traverseKey({\n key: inflection.singularize(key),\n value: recordDef.keyType,\n messages,\n enums,\n isOptional: false,\n isInArray: true,\n typePrefix,\n parentKey,\n });\n const valueType = traverseKey({\n key: inflection.singularize(key),\n value: recordDef.valueType,\n messages,\n enums,\n isOptional: false,\n isInArray: true,\n typePrefix,\n parentKey,\n });\n\n if (!keyType[0] || keyType.length !== 1) {\n return [];\n }\n\n if (!valueType[0] || valueType.length !== 1) {\n return [];\n }\n\n const mapType = `map<${protobufFieldToType({ field: keyType[0] })}, ${protobufFieldToType({ field: valueType[0] })}>`;\n return [\n {\n types: [mapType],\n name: key,\n },\n ];\n};\n\n/**\n * Traverses a single key-value pair from a Zod schema and converts it to protobuf field definitions.\n * Handles various Zod types including primitives, objects, arrays, maps, enums, tuples, and optional/nullable fields.\n *\n * @param key - Field name\n * @param value - Zod schema value\n * @param messages - Map of message names to their protobuf fields\n * @param enums - Map of enum names to their protobuf values\n * @param isOptional - Whether the field is optional\n * @param isInArray - Whether the field is inside an array\n * @param typePrefix - Optional prefix for type names\n * @param parentKey - Optional parent message name for nested types\n * @returns Array of protobuf field definitions\n */\nexport const traverseKey = ({\n key,\n value,\n messages,\n enums,\n isOptional,\n isInArray,\n typePrefix,\n parentKey,\n}: {\n key: string;\n value: unknown;\n messages: Map<string, string[]>;\n enums: Map<string, string[]>;\n isOptional: boolean;\n isInArray: boolean;\n typePrefix: string | null;\n parentKey?: string;\n}): ProtobufField[] => {\n if (!value) {\n return [];\n }\n\n if (value instanceof ZodOptional || value instanceof ZodNullable) {\n return traverseKey({\n key,\n value: value.unwrap(),\n messages,\n enums,\n isOptional: true,\n isInArray,\n typePrefix,\n parentKey,\n });\n }\n\n if (value instanceof ZodArray || value instanceof ZodSet) {\n return traverseArray({\n key,\n value: value as ZodArray<ZodTypeAny> | ZodSet<ZodTypeAny>,\n messages,\n enums,\n typePrefix,\n parentKey,\n });\n }\n\n if (value instanceof ZodMap) {\n return traverseMap({\n key,\n value: value as ZodMap<ZodTypeAny, ZodTypeAny>,\n messages,\n enums,\n typePrefix,\n parentKey,\n });\n }\n\n if (value instanceof ZodRecord) {\n return traverseRecord({\n key,\n value: value as ZodRecord,\n messages,\n enums,\n typePrefix,\n parentKey,\n });\n }\n\n const optional = isOptional && !isInArray ? \"optional\" : null;\n\n if (value instanceof ZodObject) {\n let messageName = toPascalCase({ value: key });\n if (parentKey) {\n const isParentAlreadyPascalCase = /^[A-Z][a-zA-Z0-9]*$/.test(parentKey);\n if (isParentAlreadyPascalCase) {\n messageName = `${parentKey}${messageName}`;\n } else {\n const parentMessageName = toPascalCase({ value: parentKey });\n messageName = `${parentMessageName}${messageName}`;\n }\n }\n if (typePrefix) {\n messageName = `${typePrefix}${messageName}`;\n }\n const nestedMessageFields = traverseSchema({\n schema: value,\n messages,\n enums,\n typePrefix,\n parentKey: messageName,\n });\n messages.set(messageName, nestedMessageFields);\n return [\n {\n types: [optional, messageName],\n name: key,\n },\n ];\n }\n\n if (value instanceof ZodString) {\n return [\n {\n types: [optional, \"string\"],\n name: key,\n },\n ];\n }\n\n if (value instanceof ZodNumber) {\n const typeName = getNumberTypeName({ value });\n return [\n {\n types: [optional, typeName],\n name: key,\n },\n ];\n }\n\n if (value instanceof ZodBoolean) {\n return [\n {\n types: [optional, \"bool\"],\n name: key,\n },\n ];\n }\n\n if (value instanceof ZodEnum) {\n const enumFields = value.options\n .map(\n (option: string | number, index: number) =>\n ` ${String(option)} = ${index};`,\n )\n .join(\"\\n\");\n let enumName = toPascalCase({ value: key });\n if (parentKey) {\n const isParentAlreadyPascalCase = /^[A-Z][a-zA-Z0-9]*$/.test(parentKey);\n if (isParentAlreadyPascalCase) {\n enumName = `${parentKey}${enumName}`;\n } else {\n const parentMessageName = toPascalCase({ value: parentKey });\n enumName = `${parentMessageName}${enumName}`;\n }\n }\n if (typePrefix) {\n enumName = `${typePrefix}${enumName}`;\n }\n enums.set(enumName, [`enum ${enumName} {\\n${enumFields}\\n}`]);\n return [\n {\n types: [optional, enumName],\n name: key,\n },\n ];\n }\n\n if (value instanceof ZodDate) {\n return [\n {\n types: [optional, \"string\"],\n name: key,\n },\n ];\n }\n\n if (value instanceof ZodBigInt) {\n return [\n {\n types: [optional, \"int64\"],\n name: key,\n },\n ];\n }\n\n if (value instanceof ZodType) {\n const def = value.def as {\n type?: string;\n check?: unknown;\n fn?: (data: unknown) => boolean;\n };\n if (def.type === \"custom\" && def.check === \"custom\" && def.fn) {\n try {\n if (\n (typeof Buffer !== \"undefined\" && def.fn(Buffer.alloc(0))) ||\n (typeof Uint8Array !== \"undefined\" && def.fn(new Uint8Array(0)))\n ) {\n return [\n {\n types: [optional, \"bytes\"],\n name: key,\n },\n ];\n }\n } catch {}\n }\n }\n\n if (value instanceof ZodTuple) {\n const tupleFields: ProtobufField[] = (\n value.def.items as ZodTypeAny[]\n ).flatMap((item: ZodTypeAny, index: number) => {\n return traverseKey({\n key: `${key}_${index}`,\n value: item,\n messages,\n enums,\n isOptional: false,\n isInArray,\n typePrefix,\n parentKey,\n });\n });\n\n let tupleMessageName = toPascalCase({ value: key });\n if (parentKey) {\n const isParentAlreadyPascalCase = /^[A-Z][a-zA-Z0-9]*$/.test(parentKey);\n if (isParentAlreadyPascalCase) {\n tupleMessageName = `${parentKey}${tupleMessageName}`;\n } else {\n const parentMessageName = toPascalCase({ value: parentKey });\n tupleMessageName = `${parentMessageName}${tupleMessageName}`;\n }\n }\n if (typePrefix) {\n tupleMessageName = `${typePrefix}${tupleMessageName}`;\n }\n messages.set(\n tupleMessageName,\n tupleFields.map(\n (field, index) =>\n ` ${field.types.join(\" \")} ${field.name} = ${index + 1};`,\n ),\n );\n return [\n {\n types: [optional, tupleMessageName],\n name: key,\n },\n ];\n }\n\n if (value instanceof ZodType) {\n return [];\n }\n\n return [];\n};\n\n/**\n * Traverses a Zod object schema and converts it to protobuf message field definitions.\n * Processes all fields in the schema and generates appropriate protobuf types.\n *\n * @param schema - Zod schema to traverse\n * @param messages - Map of message names to their protobuf fields\n * @param enums - Map of enum names to their protobuf values\n * @param typePrefix - Optional prefix for type names\n * @param parentKey - Optional parent message name for nested types\n * @returns Array of protobuf field definition strings\n */\nexport const traverseSchema = ({\n schema,\n messages,\n enums,\n typePrefix,\n parentKey,\n}: {\n schema: ZodTypeAny;\n messages: Map<string, string[]>;\n enums: Map<string, string[]>;\n typePrefix: string | null;\n parentKey?: string;\n}): string[] => {\n if (\n !schema ||\n typeof schema !== \"object\" ||\n !(\"def\" in schema) ||\n (schema.constructor.name !== \"ZodObject\" &&\n (schema.def as { type?: string }).type !== \"object\")\n ) {\n return [];\n }\n\n const zodObject = schema as ZodObject<any>;\n const fields = Object.entries(zodObject.shape).flatMap(([key, value]) => {\n return traverseKey({\n key,\n value,\n messages,\n enums,\n isOptional: false,\n isInArray: false,\n typePrefix,\n parentKey,\n });\n });\n\n return fields.map(\n (field, index) =>\n `${protobufFieldToType({ field })} ${field.name} = ${index + 1};`,\n );\n};\n","import { z, ZodObject, type ZodTypeAny } from \"zod\";\nimport type {\n ServiceDefinition,\n ServiceMethod,\n ServicesInput,\n ZodFunctionDefinition,\n ZodTupleDefinition,\n} from \"./types\";\nimport { toPascalCase } from \"./utils\";\nimport { traverseSchema } from \"./traversers\";\n\n/**\n * Context for generating protobuf services.\n * Contains accumulated messages, enums, and type prefix.\n */\ninterface ServiceGenerationContext {\n /** Map of message names to their protobuf fields */\n messages: Map<string, string[]>;\n /** Map of enum names to their protobuf values */\n enums: Map<string, string[]>;\n /** Prefix for type names or null if prefix is not used */\n typePrefix: string | null;\n}\n\n/**\n * Parses a Zod service schema and extracts method definitions.\n * Each method must be a function with one argument (request) and a return value (response).\n *\n * @param name - Service name\n * @param schema - Zod object containing service methods as functions\n * @returns Service definition with extracted methods\n */\nconst parseZodServiceSchema = (\n name: string,\n schema: ZodObject<Record<string, ZodTypeAny>>,\n): ServiceDefinition => {\n const shape = schema.shape as Record<string, ZodTypeAny>;\n const methods: ServiceMethod[] = [];\n\n for (const [methodName, methodSchema] of Object.entries(shape)) {\n const methodDef = (methodSchema as ZodTypeAny).def as ZodFunctionDefinition;\n\n if (methodDef.type === \"function\") {\n const inputDef = methodDef.input;\n\n const args = (inputDef?.def as ZodTupleDefinition)?.items ?? [];\n const output = methodDef.output as ZodTypeAny;\n\n if (args.length > 0 && args[0] && output) {\n const request = args[0];\n const response = output;\n\n let streaming: \"client\" | \"server\" | \"bidirectional\" | undefined;\n const metadata = methodSchema.meta();\n streaming = metadata?.streaming as\n | \"client\"\n | \"server\"\n | \"bidirectional\"\n | undefined;\n\n methods.push({\n name: methodName,\n request,\n response,\n streaming,\n });\n }\n }\n }\n\n return {\n name,\n methods,\n };\n};\n\n/**\n * Normalizes service input data into an array of service definitions.\n * If an array is passed, returns it as is.\n * If an object is passed, converts each key-value pair into a service definition.\n *\n * @param services - Array of service definitions or object with Zod schemas\n * @returns Array of normalized service definitions\n */\nconst normalizeServices = (services: ServicesInput): ServiceDefinition[] => {\n if (Array.isArray(services)) {\n return services;\n }\n\n return Object.entries(services).map(([name, schema]) =>\n parseZodServiceSchema(name, schema),\n );\n};\n\n/**\n * Ensures that the schema is a ZodObject.\n * If the schema is already an object, returns it as is.\n * Otherwise, wraps the schema in an object with a \"data\" field.\n *\n * @param schema - Zod schema of any type\n * @returns ZodObject containing the original schema\n */\nconst ensureZodObject = (\n schema: ZodTypeAny,\n): ZodObject<Record<string, ZodTypeAny>> => {\n const schemaType =\n (schema.def as { type?: string }).type || schema.constructor.name;\n\n if (schemaType === \"object\" || schema.constructor.name === \"ZodObject\") {\n return schema as ZodObject<Record<string, ZodTypeAny>>;\n }\n\n return z.object({\n data: schema,\n });\n};\n\n/**\n * Generates the name for a request message based on the method name.\n *\n * @param methodName - Name of the service method\n * @param typePrefix - Optional prefix for type names\n * @returns Generated request message name in PascalCase\n */\nconst generateRequestMessageName = (\n methodName: string,\n typePrefix: string | null,\n): string => {\n const messageName = toPascalCase({ value: `${methodName}Request` });\n return typePrefix ? `${typePrefix}${messageName}` : messageName;\n};\n\n/**\n * Generates the name for a response message based on the method name.\n *\n * @param methodName - Name of the service method\n * @param typePrefix - Optional prefix for type names\n * @returns Generated response message name in PascalCase\n */\nconst generateResponseMessageName = (\n methodName: string,\n typePrefix: string | null,\n): string => {\n const messageName = toPascalCase({ value: `${methodName}Response` });\n return typePrefix ? `${typePrefix}${messageName}` : messageName;\n};\n\n/**\n * Processes a service method by generating request and response message names\n * and traversing their schemas to populate the context with message definitions.\n *\n * @param method - Service method definition\n * @param context - Generation context containing messages, enums, and type prefix\n * @returns Object containing request and response message names\n */\nconst processServiceMethod = (\n method: ServiceMethod,\n context: ServiceGenerationContext,\n): { requestName: string; responseName: string } => {\n const { messages, enums, typePrefix } = context;\n\n const requestName = generateRequestMessageName(method.name, typePrefix);\n const responseName = generateResponseMessageName(method.name, typePrefix);\n\n if (!messages.has(requestName)) {\n const requestSchema = ensureZodObject(method.request);\n const requestFields = traverseSchema({\n schema: requestSchema,\n messages,\n enums,\n typePrefix,\n parentKey: requestName,\n });\n messages.set(requestName, requestFields);\n }\n\n if (!messages.has(responseName)) {\n const responseSchema = ensureZodObject(method.response);\n const responseFields = traverseSchema({\n schema: responseSchema,\n messages,\n enums,\n typePrefix,\n parentKey: responseName,\n });\n messages.set(responseName, responseFields);\n }\n\n return { requestName, responseName };\n};\n\n/**\n * Generates protobuf service definitions from Zod service schemas.\n * Supports streaming methods (client, server, bidirectional).\n *\n * @param services - Service definitions as array or object with Zod schemas\n * @param context - Generation context containing messages, enums, and type prefix\n * @returns Array of protobuf service definition strings\n */\nexport const generateServices = (\n services: ServicesInput,\n context: ServiceGenerationContext,\n): string[] => {\n const normalizedServices = normalizeServices(services);\n\n return normalizedServices.map((service) => {\n const methods = service.methods.map((method) => {\n const { requestName, responseName } = processServiceMethod(\n method,\n context,\n );\n\n const requestStreaming =\n method.streaming === \"client\" || method.streaming === \"bidirectional\";\n const responseStreaming =\n method.streaming === \"server\" || method.streaming === \"bidirectional\";\n\n const requestType = requestStreaming\n ? `stream ${requestName}`\n : requestName;\n const responseType = responseStreaming\n ? `stream ${responseName}`\n : responseName;\n\n return ` rpc ${toPascalCase({ value: method.name })}(${requestType}) returns (${responseType});`;\n });\n\n return `service ${toPascalCase({ value: service.name })} {\\n${methods.join(\"\\n\")}\\n}`;\n });\n};\n","import type { ZodTypeAny } from \"zod\";\nimport type { ZodToProtobufOptions } from \"./types\";\nimport { traverseSchema } from \"./traversers\";\nimport { generateServices } from \"./service-generator\";\nimport { z } from \"zod\";\n\n/**\n * Generates a protobuf definition string for services only (without root message).\n * Convenience function that calls zodToProtobuf with an empty schema.\n *\n * @param options - Options for protobuf generation\n * @returns Protobuf definition string\n */\nexport const zodToProtobufService = (\n options: ZodToProtobufOptions = {},\n): string => {\n return zodToProtobuf(z.object(), options);\n};\n\n/**\n * Converts a Zod schema to a protobuf definition string.\n * Generates messages, enums, and services based on the provided schema and options.\n *\n * @param schema - Optional Zod schema to convert (if not provided, only services will be generated)\n * @param options - Options for protobuf generation including package name, root message name, type prefix, and services\n * @returns Complete protobuf definition string\n */\nexport const zodToProtobuf = (\n schema?: ZodTypeAny,\n options: ZodToProtobufOptions = {},\n): string => {\n const {\n packageName = \"default\",\n rootMessageName = \"Message\",\n typePrefix = \"\",\n services,\n skipRootMessage = false,\n } = options;\n\n const messages = new Map<string, string[]>();\n const enums = new Map<string, string[]>();\n\n if (schema && !skipRootMessage) {\n const fields = traverseSchema({ schema, messages, enums, typePrefix });\n if (fields.length > 0) {\n const rootMessageKey = `${typePrefix}${rootMessageName}`;\n messages.set(rootMessageKey, fields);\n }\n }\n\n const context = {\n messages,\n enums,\n typePrefix: typePrefix || null,\n };\n\n const hasServices =\n services &&\n (Array.isArray(services)\n ? services.length > 0\n : Object.keys(services).length > 0);\n\n const servicesString = hasServices ? generateServices(services, context) : [];\n\n const enumsString = Array.from(enums.values()).map((enumDef) =>\n enumDef.join(\"\\n\"),\n );\n\n const messagesString = Array.from(messages.entries()).map(\n ([name, fields]) =>\n `message ${name} {\\n${fields.map((field) => ` ${field}`).join(\"\\n\")}\\n}`,\n );\n\n const content = [servicesString, enumsString, messagesString]\n .filter((strings) => !!strings.length)\n .map((strings) => strings.join(\"\\n\\n\"))\n .join(\"\\n\\n\");\n\n let protoDefinition: string = \"\";\n if (options.warningDeclaration !== false) {\n protoDefinition += `\n/**\n * This file was automatically generated by zod-to-proto.\n * DO NOT MODIFY IT BY HAND. Instead, modify the source Zod schema.\n */\n`;\n }\n\n protoDefinition += `\nsyntax = \"proto3\";\npackage ${packageName};\n\n${content}\n`;\n\n return protoDefinition.trim();\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["tupleFields: ProtobufField[]","methods: ServiceMethod[]","streaming: \"client\" | \"server\" | \"bidirectional\" | undefined","protoDefinition: string"],"sources":["../src/utils.ts","../src/traversers.ts","../src/service-generator.ts","../src/zod-to-protobuf.ts"],"sourcesContent":["import { ZodNumber } from \"zod\";\nimport type { ProtobufField } from \"./types\";\n\n/**\n * Determines the protobuf number type name based on Zod number schema.\n * Returns \"int32\" for integers, \"double\" for floating point numbers.\n *\n * @param value - Zod number schema\n * @returns Protobuf number type name (\"int32\" or \"double\")\n */\nexport const getNumberTypeName = ({ value }: { value: ZodNumber }): string => {\n return value.isInt ? \"int32\" : \"double\";\n};\n\n/**\n * Converts a string to PascalCase format.\n * Handles dot-separated strings by capitalizing each part.\n *\n * @param value - String to convert\n * @returns PascalCase string\n */\nexport const toPascalCase = ({ value }: { value: string }): string => {\n return value\n .split(\".\")\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join(\"\");\n};\n\n/**\n * Converts a protobuf field definition to its type string representation.\n * Filters out null/empty values and joins the remaining types.\n *\n * @param field - Protobuf field definition\n * @returns Type string for the protobuf field\n */\nexport const protobufFieldToType = ({\n field,\n}: {\n field: ProtobufField;\n}): string => {\n return field.types.filter(Boolean).join(\" \");\n};\n","import * as inflection from \"inflection\";\nimport {\n ZodArray,\n ZodBigInt,\n ZodBoolean,\n ZodDate,\n ZodEnum,\n ZodMap,\n ZodNullable,\n ZodNumber,\n ZodObject,\n ZodOptional,\n ZodRecord,\n ZodSet,\n ZodString,\n ZodTuple,\n ZodType,\n type ZodTypeAny,\n} from \"zod\";\nimport {\n ZodArrayDefinition,\n ZodMapDefinition,\n ZodRecordDefinition,\n type ProtobufField,\n} from \"./types\";\nimport { getNumberTypeName, toPascalCase, protobufFieldToType } from \"./utils\";\n\n/**\n * Traverses a Zod array or set schema and converts it to protobuf repeated fields.\n * Handles nested types and generates appropriate field definitions.\n *\n * @param key - Field name\n * @param value - Zod array or set schema\n * @param messages - Map of message names to their protobuf fields\n * @param enums - Map of enum names to their protobuf values\n * @param typePrefix - Optional prefix for type names\n * @param parentKey - Optional parent message name for nested types\n * @returns Array of protobuf field definitions\n */\nexport const traverseArray = ({\n key,\n value,\n messages,\n enums,\n typePrefix,\n parentKey,\n}: {\n key: string;\n value: ZodArray<ZodTypeAny> | ZodSet<ZodTypeAny>;\n messages: Map<string, string[]>;\n enums: Map<string, string[]>;\n typePrefix: string | null;\n parentKey?: string;\n}): ProtobufField[] => {\n const nestedValue =\n value instanceof ZodArray\n ? value.element\n : value instanceof ZodSet\n ? (value.def as unknown as ZodArrayDefinition).valueType\n : // @ts-expect-error\n (value.def as unknown as ZodArrayDefinition).element;\n\n const singularKey = inflection.singularize(key);\n const elementFields = traverseKey({\n key: singularKey,\n value: nestedValue,\n messages,\n enums,\n isOptional: false,\n isInArray: true,\n typePrefix,\n parentKey: nestedValue instanceof ZodObject ? parentKey : undefined,\n });\n return elementFields.map((field) => ({\n ...field,\n types: [\"repeated\", ...field.types],\n name: field.name.replace(singularKey, key),\n }));\n};\n\n/**\n * Traverses a Zod map schema and converts it to a protobuf map type.\n * Validates that both key and value types are simple types suitable for map keys/values.\n *\n * @param key - Field name\n * @param value - Zod map schema\n * @param messages - Map of message names to their protobuf fields\n * @param enums - Map of enum names to their protobuf values\n * @param typePrefix - Optional prefix for type names\n * @param parentKey - Optional parent message name for nested types\n * @returns Array containing a single protobuf map field definition, or empty array if invalid\n */\nexport const traverseMap = ({\n key,\n value,\n messages,\n enums,\n typePrefix,\n parentKey,\n}: {\n key: string;\n value: ZodMap<ZodTypeAny, ZodTypeAny>;\n messages: Map<string, string[]>;\n enums: Map<string, string[]>;\n typePrefix: string | null;\n parentKey?: string;\n}): ProtobufField[] => {\n const mapDef = value.def as ZodMapDefinition;\n\n const keyType = traverseKey({\n key: inflection.singularize(key),\n value: mapDef.keyType,\n messages,\n enums,\n isOptional: false,\n isInArray: true,\n typePrefix,\n parentKey,\n });\n const valueType = traverseKey({\n key: inflection.singularize(key),\n value: mapDef.valueType,\n messages,\n enums,\n isOptional: false,\n isInArray: true,\n typePrefix,\n parentKey,\n });\n\n if (!keyType[0] || keyType.length !== 1) {\n return [];\n }\n\n if (!valueType[0] || valueType.length !== 1) {\n return [];\n }\n\n const mapType = `map<${protobufFieldToType({ field: keyType[0] })}, ${protobufFieldToType({ field: valueType[0] })}>`;\n return [\n {\n types: [mapType],\n name: key,\n },\n ];\n};\n\n/**\n * Traverses a Zod record schema and converts it to a protobuf map type.\n * Similar to traverseMap but handles ZodRecord type.\n *\n * @param key - Field name\n * @param value - Zod record schema\n * @param messages - Map of message names to their protobuf fields\n * @param enums - Map of enum names to their protobuf values\n * @param typePrefix - Optional prefix for type names\n * @param parentKey - Optional parent message name for nested types\n * @returns Array containing a single protobuf map field definition, or empty array if invalid\n */\nexport const traverseRecord = ({\n key,\n value,\n messages,\n enums,\n typePrefix,\n parentKey,\n}: {\n key: string;\n value: ZodRecord;\n messages: Map<string, string[]>;\n enums: Map<string, string[]>;\n typePrefix: string | null;\n parentKey?: string;\n}): ProtobufField[] => {\n const recordDef = value.def as unknown as ZodRecordDefinition;\n\n const keyType = traverseKey({\n key: inflection.singularize(key),\n value: recordDef.keyType,\n messages,\n enums,\n isOptional: false,\n isInArray: true,\n typePrefix,\n parentKey,\n });\n const valueType = traverseKey({\n key: inflection.singularize(key),\n value: recordDef.valueType,\n messages,\n enums,\n isOptional: false,\n isInArray: true,\n typePrefix,\n parentKey,\n });\n\n if (!keyType[0] || keyType.length !== 1) {\n return [];\n }\n\n if (!valueType[0] || valueType.length !== 1) {\n return [];\n }\n\n const mapType = `map<${protobufFieldToType({ field: keyType[0] })}, ${protobufFieldToType({ field: valueType[0] })}>`;\n return [\n {\n types: [mapType],\n name: key,\n },\n ];\n};\n\n/**\n * Traverses a single key-value pair from a Zod schema and converts it to protobuf field definitions.\n * Handles various Zod types including primitives, objects, arrays, maps, enums, tuples, and optional/nullable fields.\n *\n * @param key - Field name\n * @param value - Zod schema value\n * @param messages - Map of message names to their protobuf fields\n * @param enums - Map of enum names to their protobuf values\n * @param isOptional - Whether the field is optional\n * @param isInArray - Whether the field is inside an array\n * @param typePrefix - Optional prefix for type names\n * @param parentKey - Optional parent message name for nested types\n * @returns Array of protobuf field definitions\n */\nexport const traverseKey = ({\n key,\n value,\n messages,\n enums,\n isOptional,\n isInArray,\n typePrefix,\n parentKey,\n}: {\n key: string;\n value: unknown;\n messages: Map<string, string[]>;\n enums: Map<string, string[]>;\n isOptional: boolean;\n isInArray: boolean;\n typePrefix: string | null;\n parentKey?: string;\n}): ProtobufField[] => {\n if (!value) {\n return [];\n }\n\n if (value instanceof ZodOptional || value instanceof ZodNullable) {\n return traverseKey({\n key,\n value: value.unwrap(),\n messages,\n enums,\n isOptional: true,\n isInArray,\n typePrefix,\n parentKey,\n });\n }\n\n if (value instanceof ZodArray || value instanceof ZodSet) {\n return traverseArray({\n key,\n value: value as ZodArray<ZodTypeAny> | ZodSet<ZodTypeAny>,\n messages,\n enums,\n typePrefix,\n parentKey,\n });\n }\n\n if (value instanceof ZodMap) {\n return traverseMap({\n key,\n value: value as ZodMap<ZodTypeAny, ZodTypeAny>,\n messages,\n enums,\n typePrefix,\n parentKey,\n });\n }\n\n if (value instanceof ZodRecord) {\n return traverseRecord({\n key,\n value: value as ZodRecord,\n messages,\n enums,\n typePrefix,\n parentKey,\n });\n }\n\n const optional = isOptional && !isInArray ? \"optional\" : null;\n\n if (value instanceof ZodObject) {\n let messageName = toPascalCase({ value: key });\n if (parentKey) {\n const isParentAlreadyPascalCase = /^[A-Z][a-zA-Z0-9]*$/.test(parentKey);\n if (isParentAlreadyPascalCase) {\n messageName = `${parentKey}${messageName}`;\n } else {\n const parentMessageName = toPascalCase({ value: parentKey });\n messageName = `${parentMessageName}${messageName}`;\n }\n }\n if (typePrefix) {\n messageName = `${typePrefix}${messageName}`;\n }\n const nestedMessageFields = traverseSchema({\n schema: value,\n messages,\n enums,\n typePrefix,\n parentKey: messageName,\n });\n messages.set(messageName, nestedMessageFields);\n return [\n {\n types: [optional, messageName],\n name: key,\n },\n ];\n }\n\n if (value instanceof ZodString) {\n return [\n {\n types: [optional, \"string\"],\n name: key,\n },\n ];\n }\n\n if (value instanceof ZodNumber) {\n const typeName = getNumberTypeName({ value });\n return [\n {\n types: [optional, typeName],\n name: key,\n },\n ];\n }\n\n if (value instanceof ZodBoolean) {\n return [\n {\n types: [optional, \"bool\"],\n name: key,\n },\n ];\n }\n\n if (value instanceof ZodEnum) {\n const enumFields = value.options\n .map(\n (option: string | number, index: number) =>\n ` ${String(option)} = ${index};`,\n )\n .join(\"\\n\");\n let enumName = toPascalCase({ value: key });\n if (parentKey) {\n const isParentAlreadyPascalCase = /^[A-Z][a-zA-Z0-9]*$/.test(parentKey);\n if (isParentAlreadyPascalCase) {\n enumName = `${parentKey}${enumName}`;\n } else {\n const parentMessageName = toPascalCase({ value: parentKey });\n enumName = `${parentMessageName}${enumName}`;\n }\n }\n if (typePrefix) {\n enumName = `${typePrefix}${enumName}`;\n }\n enums.set(enumName, [`enum ${enumName} {\\n${enumFields}\\n}`]);\n return [\n {\n types: [optional, enumName],\n name: key,\n },\n ];\n }\n\n if (value instanceof ZodDate) {\n return [\n {\n types: [optional, \"string\"],\n name: key,\n },\n ];\n }\n\n if (value instanceof ZodBigInt) {\n return [\n {\n types: [optional, \"int64\"],\n name: key,\n },\n ];\n }\n\n if (value instanceof ZodType) {\n const def = value.def as {\n type?: string;\n check?: unknown;\n fn?: (data: unknown) => boolean;\n };\n if (def.type === \"custom\" && def.check === \"custom\" && def.fn) {\n try {\n if (\n (typeof Buffer !== \"undefined\" && def.fn(Buffer.alloc(0))) ||\n (typeof Uint8Array !== \"undefined\" && def.fn(new Uint8Array(0)))\n ) {\n return [\n {\n types: [optional, \"bytes\"],\n name: key,\n },\n ];\n }\n } catch {}\n }\n }\n\n if (value instanceof ZodTuple) {\n const tupleFields: ProtobufField[] = (\n value.def.items as ZodTypeAny[]\n ).flatMap((item: ZodTypeAny, index: number) => {\n return traverseKey({\n key: `${key}_${index}`,\n value: item,\n messages,\n enums,\n isOptional: false,\n isInArray,\n typePrefix,\n parentKey,\n });\n });\n\n let tupleMessageName = toPascalCase({ value: key });\n if (parentKey) {\n const isParentAlreadyPascalCase = /^[A-Z][a-zA-Z0-9]*$/.test(parentKey);\n if (isParentAlreadyPascalCase) {\n tupleMessageName = `${parentKey}${tupleMessageName}`;\n } else {\n const parentMessageName = toPascalCase({ value: parentKey });\n tupleMessageName = `${parentMessageName}${tupleMessageName}`;\n }\n }\n if (typePrefix) {\n tupleMessageName = `${typePrefix}${tupleMessageName}`;\n }\n messages.set(\n tupleMessageName,\n tupleFields.map(\n (field, index) =>\n ` ${field.types.join(\" \")} ${field.name} = ${index + 1};`,\n ),\n );\n return [\n {\n types: [optional, tupleMessageName],\n name: key,\n },\n ];\n }\n\n if (value instanceof ZodType) {\n return [];\n }\n\n return [];\n};\n\n/**\n * Traverses a Zod object schema and converts it to protobuf message field definitions.\n * Processes all fields in the schema and generates appropriate protobuf types.\n *\n * @param schema - Zod schema to traverse\n * @param messages - Map of message names to their protobuf fields\n * @param enums - Map of enum names to their protobuf values\n * @param typePrefix - Optional prefix for type names\n * @param parentKey - Optional parent message name for nested types\n * @returns Array of protobuf field definition strings\n */\nexport const traverseSchema = ({\n schema,\n messages,\n enums,\n typePrefix,\n parentKey,\n}: {\n schema: ZodTypeAny;\n messages: Map<string, string[]>;\n enums: Map<string, string[]>;\n typePrefix: string | null;\n parentKey?: string;\n}): string[] => {\n if (\n !schema ||\n typeof schema !== \"object\" ||\n !(\"def\" in schema) ||\n (schema.constructor.name !== \"ZodObject\" &&\n (schema.def as { type?: string }).type !== \"object\")\n ) {\n return [];\n }\n\n const zodObject = schema as ZodObject<any>;\n const fields = Object.entries(zodObject.shape).flatMap(([key, value]) => {\n return traverseKey({\n key,\n value,\n messages,\n enums,\n isOptional: false,\n isInArray: false,\n typePrefix,\n parentKey,\n });\n });\n\n return fields.map(\n (field, index) =>\n `${protobufFieldToType({ field })} ${field.name} = ${index + 1};`,\n );\n};\n","import { z, ZodObject, type ZodTypeAny } from \"zod\";\nimport type {\n ServiceDefinition,\n ServiceMethod,\n ServicesInput,\n ZodFunctionDefinition,\n ZodTupleDefinition,\n} from \"./types\";\nimport { toPascalCase } from \"./utils\";\nimport { traverseSchema } from \"./traversers\";\n\n/**\n * Context for generating protobuf services.\n * Contains accumulated messages, enums, and type prefix.\n */\ninterface ServiceGenerationContext {\n /** Map of message names to their protobuf fields */\n messages: Map<string, string[]>;\n /** Map of enum names to their protobuf values */\n enums: Map<string, string[]>;\n /** Prefix for type names or null if prefix is not used */\n typePrefix: string | null;\n}\n\n/**\n * Parses a Zod service schema and extracts method definitions.\n * Each method must be a function with one argument (request) and a return value (response).\n *\n * @param name - Service name\n * @param schema - Zod object containing service methods as functions\n * @returns Service definition with extracted methods\n */\nconst parseZodServiceSchema = (\n name: string,\n schema: ZodObject<Record<string, ZodTypeAny>>,\n): ServiceDefinition => {\n const shape = schema.shape as Record<string, ZodTypeAny>;\n const methods: ServiceMethod[] = [];\n\n for (const [methodName, methodSchema] of Object.entries(shape)) {\n const methodDef = (methodSchema as ZodTypeAny).def as ZodFunctionDefinition;\n\n if (methodDef.type === \"function\") {\n const inputDef = methodDef.input;\n\n const args = (inputDef?.def as ZodTupleDefinition)?.items ?? [];\n const output = methodDef.output as ZodTypeAny;\n\n if (args.length > 0 && args[0] && output) {\n const request = args[0];\n const response = output;\n\n let streaming: \"client\" | \"server\" | \"bidirectional\" | undefined;\n const metadata = methodSchema.meta();\n streaming = metadata?.streaming as\n | \"client\"\n | \"server\"\n | \"bidirectional\"\n | undefined;\n\n methods.push({\n name: methodName,\n request,\n response,\n streaming,\n });\n }\n }\n }\n\n return {\n name,\n methods,\n };\n};\n\n/**\n * Normalizes service input data into an array of service definitions.\n * If an array is passed, returns it as is.\n * If an object is passed, converts each key-value pair into a service definition.\n *\n * @param services - Array of service definitions or object with Zod schemas\n * @returns Array of normalized service definitions\n */\nconst normalizeServices = (services: ServicesInput): ServiceDefinition[] => {\n if (Array.isArray(services)) {\n return services;\n }\n\n return Object.entries(services).map(([name, schema]) =>\n parseZodServiceSchema(name, schema),\n );\n};\n\n/**\n * Ensures that the schema is a ZodObject.\n * If the schema is already an object, returns it as is.\n * Otherwise, wraps the schema in an object with a \"data\" field.\n *\n * @param schema - Zod schema of any type\n * @returns ZodObject containing the original schema\n */\nconst ensureZodObject = (\n schema: ZodTypeAny,\n): ZodObject<Record<string, ZodTypeAny>> => {\n const schemaType =\n (schema.def as { type?: string }).type || schema.constructor.name;\n\n if (schemaType === \"object\" || schema.constructor.name === \"ZodObject\") {\n return schema as ZodObject<Record<string, ZodTypeAny>>;\n }\n\n return z.object({\n data: schema,\n });\n};\n\n/**\n * Generates the name for a request message based on the method name.\n *\n * @param methodName - Name of the service method\n * @param typePrefix - Optional prefix for type names\n * @returns Generated request message name in PascalCase\n */\nconst generateRequestMessageName = (\n methodName: string,\n typePrefix: string | null,\n): string => {\n const messageName = toPascalCase({ value: `${methodName}Request` });\n return typePrefix ? `${typePrefix}${messageName}` : messageName;\n};\n\n/**\n * Generates the name for a response message based on the method name.\n *\n * @param methodName - Name of the service method\n * @param typePrefix - Optional prefix for type names\n * @returns Generated response message name in PascalCase\n */\nconst generateResponseMessageName = (\n methodName: string,\n typePrefix: string | null,\n): string => {\n const messageName = toPascalCase({ value: `${methodName}Response` });\n return typePrefix ? `${typePrefix}${messageName}` : messageName;\n};\n\n/**\n * Processes a service method by generating request and response message names\n * and traversing their schemas to populate the context with message definitions.\n *\n * @param method - Service method definition\n * @param context - Generation context containing messages, enums, and type prefix\n * @returns Object containing request and response message names\n */\nconst processServiceMethod = (\n method: ServiceMethod,\n context: ServiceGenerationContext,\n): { requestName: string; responseName: string } => {\n const { messages, enums, typePrefix } = context;\n\n const requestName = generateRequestMessageName(method.name, typePrefix);\n const responseName = generateResponseMessageName(method.name, typePrefix);\n\n if (!messages.has(requestName)) {\n const requestSchema = ensureZodObject(method.request);\n const requestFields = traverseSchema({\n schema: requestSchema,\n messages,\n enums,\n typePrefix,\n parentKey: requestName,\n });\n messages.set(requestName, requestFields);\n }\n\n if (!messages.has(responseName)) {\n const responseSchema = ensureZodObject(method.response);\n const responseFields = traverseSchema({\n schema: responseSchema,\n messages,\n enums,\n typePrefix,\n parentKey: responseName,\n });\n messages.set(responseName, responseFields);\n }\n\n return { requestName, responseName };\n};\n\n/**\n * Generates protobuf service definitions from Zod service schemas.\n * Supports streaming methods (client, server, bidirectional).\n *\n * @param services - Service definitions as array or object with Zod schemas\n * @param context - Generation context containing messages, enums, and type prefix\n * @returns Array of protobuf service definition strings\n */\nexport const generateServices = (\n services: ServicesInput,\n context: ServiceGenerationContext,\n): string[] => {\n const normalizedServices = normalizeServices(services);\n\n return normalizedServices.map((service) => {\n const methods = service.methods.map((method) => {\n const { requestName, responseName } = processServiceMethod(\n method,\n context,\n );\n\n const requestStreaming =\n method.streaming === \"client\" || method.streaming === \"bidirectional\";\n const responseStreaming =\n method.streaming === \"server\" || method.streaming === \"bidirectional\";\n\n const requestType = requestStreaming\n ? `stream ${requestName}`\n : requestName;\n const responseType = responseStreaming\n ? `stream ${responseName}`\n : responseName;\n\n return ` rpc ${toPascalCase({ value: method.name })}(${requestType}) returns (${responseType});`;\n });\n\n return `service ${toPascalCase({ value: service.name })} {\\n${methods.join(\"\\n\")}\\n}`;\n });\n};\n","import type { ZodTypeAny } from \"zod\";\nimport type { ZodToProtobufOptions } from \"./types\";\nimport { traverseSchema } from \"./traversers\";\nimport { generateServices } from \"./service-generator\";\nimport { z } from \"zod\";\n\n/**\n * Converts a Zod schema to a protobuf definition string.\n * Generates messages, enums, and services based on the provided schema and options.\n *\n * @param schema - Optional Zod schema to convert (if not provided, only services will be generated)\n * @param options - Options for protobuf generation including package name, root message name, type prefix, and services\n * @returns Complete protobuf definition string\n */\nexport const zodToProtobufService = (\n options: ZodToProtobufOptions = {},\n): string => {\n const {\n packageName = \"default\",\n typePrefix = \"\",\n services,\n } = options;\n\n const messages = new Map<string, string[]>();\n const enums = new Map<string, string[]>();\n\n const context = {\n messages,\n enums,\n typePrefix: typePrefix || null,\n };\n\n const hasServices =\n services &&\n (Array.isArray(services)\n ? services.length > 0\n : Object.keys(services).length > 0);\n\n const servicesString = hasServices ? generateServices(services, context) : [];\n\n const enumsString = Array.from(enums.values()).map((enumDef) =>\n enumDef.join(\"\\n\"),\n );\n\n const messagesString = Array.from(messages.entries()).map(\n ([name, fields]) =>\n `message ${name} {\\n${fields.map((field) => ` ${field}`).join(\"\\n\")}\\n}`,\n );\n\n const content = [servicesString, enumsString, messagesString]\n .filter((strings) => !!strings.length)\n .map((strings) => strings.join(\"\\n\\n\"))\n .join(\"\\n\\n\");\n\n let protoDefinition: string = \"\";\n if (options.warningDeclaration !== false) {\n protoDefinition += `\n/**\n * This file was automatically generated by zod-to-proto.\n * DO NOT MODIFY IT BY HAND. Instead, modify the source Zod schema.\n */\n`;\n }\n\n protoDefinition += `\nsyntax = \"proto3\";\npackage ${packageName};\n\n${content}\n`;\n\n return protoDefinition.trim();\n};\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,31 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@globalart/zod-to-proto",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"author": {
|
|
5
5
|
"name": "GlobalArt, Inc"
|
|
6
6
|
},
|
|
7
|
-
"license": "MIT",
|
|
8
7
|
"type": "module",
|
|
8
|
+
"license": "MIT",
|
|
9
9
|
"files": [
|
|
10
10
|
"dist",
|
|
11
11
|
"README.md",
|
|
12
12
|
"LICENSE"
|
|
13
13
|
],
|
|
14
|
-
"main": "
|
|
15
|
-
"module": "
|
|
16
|
-
"types": "
|
|
17
|
-
"exports": {
|
|
18
|
-
".": {
|
|
19
|
-
"import": {
|
|
20
|
-
"types": "./dist/index.d.mts",
|
|
21
|
-
"default": "./dist/index.mjs"
|
|
22
|
-
},
|
|
23
|
-
"require": {
|
|
24
|
-
"types": "./dist/index.d.cts",
|
|
25
|
-
"default": "./dist/index.cjs"
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
},
|
|
14
|
+
"main": "dist/index.mjs",
|
|
15
|
+
"module": "dist/index.mjs",
|
|
16
|
+
"types": "dist/index.d.mts",
|
|
29
17
|
"repository": {
|
|
30
18
|
"type": "git",
|
|
31
19
|
"url": "git+https://github.com/GlobalArtInc/ecosystem.git#main"
|
package/dist/index.cjs
DELETED
|
@@ -1,549 +0,0 @@
|
|
|
1
|
-
//#region rolldown:runtime
|
|
2
|
-
var __create = Object.create;
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __copyProps = (to, from, except, desc) => {
|
|
9
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
10
|
-
for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
11
|
-
key = keys[i];
|
|
12
|
-
if (!__hasOwnProp.call(to, key) && key !== except) {
|
|
13
|
-
__defProp(to, key, {
|
|
14
|
-
get: ((k) => from[k]).bind(null, key),
|
|
15
|
-
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
16
|
-
});
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
return to;
|
|
21
|
-
};
|
|
22
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
23
|
-
value: mod,
|
|
24
|
-
enumerable: true
|
|
25
|
-
}) : target, mod));
|
|
26
|
-
|
|
27
|
-
//#endregion
|
|
28
|
-
let inflection = require("inflection");
|
|
29
|
-
inflection = __toESM(inflection);
|
|
30
|
-
let zod = require("zod");
|
|
31
|
-
|
|
32
|
-
//#region src/utils.ts
|
|
33
|
-
/**
|
|
34
|
-
* Determines the protobuf number type name based on Zod number schema.
|
|
35
|
-
* Returns "int32" for integers, "double" for floating point numbers.
|
|
36
|
-
*
|
|
37
|
-
* @param value - Zod number schema
|
|
38
|
-
* @returns Protobuf number type name ("int32" or "double")
|
|
39
|
-
*/
|
|
40
|
-
const getNumberTypeName = ({ value }) => {
|
|
41
|
-
return value.isInt ? "int32" : "double";
|
|
42
|
-
};
|
|
43
|
-
/**
|
|
44
|
-
* Converts a string to PascalCase format.
|
|
45
|
-
* Handles dot-separated strings by capitalizing each part.
|
|
46
|
-
*
|
|
47
|
-
* @param value - String to convert
|
|
48
|
-
* @returns PascalCase string
|
|
49
|
-
*/
|
|
50
|
-
const toPascalCase = ({ value }) => {
|
|
51
|
-
return value.split(".").map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
|
|
52
|
-
};
|
|
53
|
-
/**
|
|
54
|
-
* Converts a protobuf field definition to its type string representation.
|
|
55
|
-
* Filters out null/empty values and joins the remaining types.
|
|
56
|
-
*
|
|
57
|
-
* @param field - Protobuf field definition
|
|
58
|
-
* @returns Type string for the protobuf field
|
|
59
|
-
*/
|
|
60
|
-
const protobufFieldToType = ({ field }) => {
|
|
61
|
-
return field.types.filter(Boolean).join(" ");
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
//#endregion
|
|
65
|
-
//#region src/traversers.ts
|
|
66
|
-
/**
|
|
67
|
-
* Traverses a Zod array or set schema and converts it to protobuf repeated fields.
|
|
68
|
-
* Handles nested types and generates appropriate field definitions.
|
|
69
|
-
*
|
|
70
|
-
* @param key - Field name
|
|
71
|
-
* @param value - Zod array or set schema
|
|
72
|
-
* @param messages - Map of message names to their protobuf fields
|
|
73
|
-
* @param enums - Map of enum names to their protobuf values
|
|
74
|
-
* @param typePrefix - Optional prefix for type names
|
|
75
|
-
* @param parentKey - Optional parent message name for nested types
|
|
76
|
-
* @returns Array of protobuf field definitions
|
|
77
|
-
*/
|
|
78
|
-
const traverseArray = ({ key, value, messages, enums, typePrefix, parentKey }) => {
|
|
79
|
-
const nestedValue = value instanceof zod.ZodArray ? value.element : value instanceof zod.ZodSet ? value.def.valueType : value.def.element;
|
|
80
|
-
const singularKey = inflection.singularize(key);
|
|
81
|
-
return traverseKey({
|
|
82
|
-
key: singularKey,
|
|
83
|
-
value: nestedValue,
|
|
84
|
-
messages,
|
|
85
|
-
enums,
|
|
86
|
-
isOptional: false,
|
|
87
|
-
isInArray: true,
|
|
88
|
-
typePrefix,
|
|
89
|
-
parentKey: nestedValue instanceof zod.ZodObject ? parentKey : void 0
|
|
90
|
-
}).map((field) => ({
|
|
91
|
-
...field,
|
|
92
|
-
types: ["repeated", ...field.types],
|
|
93
|
-
name: field.name.replace(singularKey, key)
|
|
94
|
-
}));
|
|
95
|
-
};
|
|
96
|
-
/**
|
|
97
|
-
* Traverses a Zod map schema and converts it to a protobuf map type.
|
|
98
|
-
* Validates that both key and value types are simple types suitable for map keys/values.
|
|
99
|
-
*
|
|
100
|
-
* @param key - Field name
|
|
101
|
-
* @param value - Zod map schema
|
|
102
|
-
* @param messages - Map of message names to their protobuf fields
|
|
103
|
-
* @param enums - Map of enum names to their protobuf values
|
|
104
|
-
* @param typePrefix - Optional prefix for type names
|
|
105
|
-
* @param parentKey - Optional parent message name for nested types
|
|
106
|
-
* @returns Array containing a single protobuf map field definition, or empty array if invalid
|
|
107
|
-
*/
|
|
108
|
-
const traverseMap = ({ key, value, messages, enums, typePrefix, parentKey }) => {
|
|
109
|
-
const mapDef = value.def;
|
|
110
|
-
const keyType = traverseKey({
|
|
111
|
-
key: inflection.singularize(key),
|
|
112
|
-
value: mapDef.keyType,
|
|
113
|
-
messages,
|
|
114
|
-
enums,
|
|
115
|
-
isOptional: false,
|
|
116
|
-
isInArray: true,
|
|
117
|
-
typePrefix,
|
|
118
|
-
parentKey
|
|
119
|
-
});
|
|
120
|
-
const valueType = traverseKey({
|
|
121
|
-
key: inflection.singularize(key),
|
|
122
|
-
value: mapDef.valueType,
|
|
123
|
-
messages,
|
|
124
|
-
enums,
|
|
125
|
-
isOptional: false,
|
|
126
|
-
isInArray: true,
|
|
127
|
-
typePrefix,
|
|
128
|
-
parentKey
|
|
129
|
-
});
|
|
130
|
-
if (!keyType[0] || keyType.length !== 1) return [];
|
|
131
|
-
if (!valueType[0] || valueType.length !== 1) return [];
|
|
132
|
-
return [{
|
|
133
|
-
types: [`map<${protobufFieldToType({ field: keyType[0] })}, ${protobufFieldToType({ field: valueType[0] })}>`],
|
|
134
|
-
name: key
|
|
135
|
-
}];
|
|
136
|
-
};
|
|
137
|
-
/**
|
|
138
|
-
* Traverses a Zod record schema and converts it to a protobuf map type.
|
|
139
|
-
* Similar to traverseMap but handles ZodRecord type.
|
|
140
|
-
*
|
|
141
|
-
* @param key - Field name
|
|
142
|
-
* @param value - Zod record schema
|
|
143
|
-
* @param messages - Map of message names to their protobuf fields
|
|
144
|
-
* @param enums - Map of enum names to their protobuf values
|
|
145
|
-
* @param typePrefix - Optional prefix for type names
|
|
146
|
-
* @param parentKey - Optional parent message name for nested types
|
|
147
|
-
* @returns Array containing a single protobuf map field definition, or empty array if invalid
|
|
148
|
-
*/
|
|
149
|
-
const traverseRecord = ({ key, value, messages, enums, typePrefix, parentKey }) => {
|
|
150
|
-
const recordDef = value.def;
|
|
151
|
-
const keyType = traverseKey({
|
|
152
|
-
key: inflection.singularize(key),
|
|
153
|
-
value: recordDef.keyType,
|
|
154
|
-
messages,
|
|
155
|
-
enums,
|
|
156
|
-
isOptional: false,
|
|
157
|
-
isInArray: true,
|
|
158
|
-
typePrefix,
|
|
159
|
-
parentKey
|
|
160
|
-
});
|
|
161
|
-
const valueType = traverseKey({
|
|
162
|
-
key: inflection.singularize(key),
|
|
163
|
-
value: recordDef.valueType,
|
|
164
|
-
messages,
|
|
165
|
-
enums,
|
|
166
|
-
isOptional: false,
|
|
167
|
-
isInArray: true,
|
|
168
|
-
typePrefix,
|
|
169
|
-
parentKey
|
|
170
|
-
});
|
|
171
|
-
if (!keyType[0] || keyType.length !== 1) return [];
|
|
172
|
-
if (!valueType[0] || valueType.length !== 1) return [];
|
|
173
|
-
return [{
|
|
174
|
-
types: [`map<${protobufFieldToType({ field: keyType[0] })}, ${protobufFieldToType({ field: valueType[0] })}>`],
|
|
175
|
-
name: key
|
|
176
|
-
}];
|
|
177
|
-
};
|
|
178
|
-
/**
|
|
179
|
-
* Traverses a single key-value pair from a Zod schema and converts it to protobuf field definitions.
|
|
180
|
-
* Handles various Zod types including primitives, objects, arrays, maps, enums, tuples, and optional/nullable fields.
|
|
181
|
-
*
|
|
182
|
-
* @param key - Field name
|
|
183
|
-
* @param value - Zod schema value
|
|
184
|
-
* @param messages - Map of message names to their protobuf fields
|
|
185
|
-
* @param enums - Map of enum names to their protobuf values
|
|
186
|
-
* @param isOptional - Whether the field is optional
|
|
187
|
-
* @param isInArray - Whether the field is inside an array
|
|
188
|
-
* @param typePrefix - Optional prefix for type names
|
|
189
|
-
* @param parentKey - Optional parent message name for nested types
|
|
190
|
-
* @returns Array of protobuf field definitions
|
|
191
|
-
*/
|
|
192
|
-
const traverseKey = ({ key, value, messages, enums, isOptional, isInArray, typePrefix, parentKey }) => {
|
|
193
|
-
if (!value) return [];
|
|
194
|
-
if (value instanceof zod.ZodOptional || value instanceof zod.ZodNullable) return traverseKey({
|
|
195
|
-
key,
|
|
196
|
-
value: value.unwrap(),
|
|
197
|
-
messages,
|
|
198
|
-
enums,
|
|
199
|
-
isOptional: true,
|
|
200
|
-
isInArray,
|
|
201
|
-
typePrefix,
|
|
202
|
-
parentKey
|
|
203
|
-
});
|
|
204
|
-
if (value instanceof zod.ZodArray || value instanceof zod.ZodSet) return traverseArray({
|
|
205
|
-
key,
|
|
206
|
-
value,
|
|
207
|
-
messages,
|
|
208
|
-
enums,
|
|
209
|
-
typePrefix,
|
|
210
|
-
parentKey
|
|
211
|
-
});
|
|
212
|
-
if (value instanceof zod.ZodMap) return traverseMap({
|
|
213
|
-
key,
|
|
214
|
-
value,
|
|
215
|
-
messages,
|
|
216
|
-
enums,
|
|
217
|
-
typePrefix,
|
|
218
|
-
parentKey
|
|
219
|
-
});
|
|
220
|
-
if (value instanceof zod.ZodRecord) return traverseRecord({
|
|
221
|
-
key,
|
|
222
|
-
value,
|
|
223
|
-
messages,
|
|
224
|
-
enums,
|
|
225
|
-
typePrefix,
|
|
226
|
-
parentKey
|
|
227
|
-
});
|
|
228
|
-
const optional = isOptional && !isInArray ? "optional" : null;
|
|
229
|
-
if (value instanceof zod.ZodObject) {
|
|
230
|
-
let messageName = toPascalCase({ value: key });
|
|
231
|
-
if (parentKey) if (/^[A-Z][a-zA-Z0-9]*$/.test(parentKey)) messageName = `${parentKey}${messageName}`;
|
|
232
|
-
else messageName = `${toPascalCase({ value: parentKey })}${messageName}`;
|
|
233
|
-
if (typePrefix) messageName = `${typePrefix}${messageName}`;
|
|
234
|
-
const nestedMessageFields = traverseSchema({
|
|
235
|
-
schema: value,
|
|
236
|
-
messages,
|
|
237
|
-
enums,
|
|
238
|
-
typePrefix,
|
|
239
|
-
parentKey: messageName
|
|
240
|
-
});
|
|
241
|
-
messages.set(messageName, nestedMessageFields);
|
|
242
|
-
return [{
|
|
243
|
-
types: [optional, messageName],
|
|
244
|
-
name: key
|
|
245
|
-
}];
|
|
246
|
-
}
|
|
247
|
-
if (value instanceof zod.ZodString) return [{
|
|
248
|
-
types: [optional, "string"],
|
|
249
|
-
name: key
|
|
250
|
-
}];
|
|
251
|
-
if (value instanceof zod.ZodNumber) return [{
|
|
252
|
-
types: [optional, getNumberTypeName({ value })],
|
|
253
|
-
name: key
|
|
254
|
-
}];
|
|
255
|
-
if (value instanceof zod.ZodBoolean) return [{
|
|
256
|
-
types: [optional, "bool"],
|
|
257
|
-
name: key
|
|
258
|
-
}];
|
|
259
|
-
if (value instanceof zod.ZodEnum) {
|
|
260
|
-
const enumFields = value.options.map((option, index) => ` ${String(option)} = ${index};`).join("\n");
|
|
261
|
-
let enumName = toPascalCase({ value: key });
|
|
262
|
-
if (parentKey) if (/^[A-Z][a-zA-Z0-9]*$/.test(parentKey)) enumName = `${parentKey}${enumName}`;
|
|
263
|
-
else enumName = `${toPascalCase({ value: parentKey })}${enumName}`;
|
|
264
|
-
if (typePrefix) enumName = `${typePrefix}${enumName}`;
|
|
265
|
-
enums.set(enumName, [`enum ${enumName} {\n${enumFields}\n}`]);
|
|
266
|
-
return [{
|
|
267
|
-
types: [optional, enumName],
|
|
268
|
-
name: key
|
|
269
|
-
}];
|
|
270
|
-
}
|
|
271
|
-
if (value instanceof zod.ZodDate) return [{
|
|
272
|
-
types: [optional, "string"],
|
|
273
|
-
name: key
|
|
274
|
-
}];
|
|
275
|
-
if (value instanceof zod.ZodBigInt) return [{
|
|
276
|
-
types: [optional, "int64"],
|
|
277
|
-
name: key
|
|
278
|
-
}];
|
|
279
|
-
if (value instanceof zod.ZodType) {
|
|
280
|
-
const def = value.def;
|
|
281
|
-
if (def.type === "custom" && def.check === "custom" && def.fn) try {
|
|
282
|
-
if (typeof Buffer !== "undefined" && def.fn(Buffer.alloc(0)) || typeof Uint8Array !== "undefined" && def.fn(new Uint8Array(0))) return [{
|
|
283
|
-
types: [optional, "bytes"],
|
|
284
|
-
name: key
|
|
285
|
-
}];
|
|
286
|
-
} catch {}
|
|
287
|
-
}
|
|
288
|
-
if (value instanceof zod.ZodTuple) {
|
|
289
|
-
const tupleFields = value.def.items.flatMap((item, index) => {
|
|
290
|
-
return traverseKey({
|
|
291
|
-
key: `${key}_${index}`,
|
|
292
|
-
value: item,
|
|
293
|
-
messages,
|
|
294
|
-
enums,
|
|
295
|
-
isOptional: false,
|
|
296
|
-
isInArray,
|
|
297
|
-
typePrefix,
|
|
298
|
-
parentKey
|
|
299
|
-
});
|
|
300
|
-
});
|
|
301
|
-
let tupleMessageName = toPascalCase({ value: key });
|
|
302
|
-
if (parentKey) if (/^[A-Z][a-zA-Z0-9]*$/.test(parentKey)) tupleMessageName = `${parentKey}${tupleMessageName}`;
|
|
303
|
-
else tupleMessageName = `${toPascalCase({ value: parentKey })}${tupleMessageName}`;
|
|
304
|
-
if (typePrefix) tupleMessageName = `${typePrefix}${tupleMessageName}`;
|
|
305
|
-
messages.set(tupleMessageName, tupleFields.map((field, index) => ` ${field.types.join(" ")} ${field.name} = ${index + 1};`));
|
|
306
|
-
return [{
|
|
307
|
-
types: [optional, tupleMessageName],
|
|
308
|
-
name: key
|
|
309
|
-
}];
|
|
310
|
-
}
|
|
311
|
-
if (value instanceof zod.ZodType) return [];
|
|
312
|
-
return [];
|
|
313
|
-
};
|
|
314
|
-
/**
|
|
315
|
-
* Traverses a Zod object schema and converts it to protobuf message field definitions.
|
|
316
|
-
* Processes all fields in the schema and generates appropriate protobuf types.
|
|
317
|
-
*
|
|
318
|
-
* @param schema - Zod schema to traverse
|
|
319
|
-
* @param messages - Map of message names to their protobuf fields
|
|
320
|
-
* @param enums - Map of enum names to their protobuf values
|
|
321
|
-
* @param typePrefix - Optional prefix for type names
|
|
322
|
-
* @param parentKey - Optional parent message name for nested types
|
|
323
|
-
* @returns Array of protobuf field definition strings
|
|
324
|
-
*/
|
|
325
|
-
const traverseSchema = ({ schema, messages, enums, typePrefix, parentKey }) => {
|
|
326
|
-
if (!schema || typeof schema !== "object" || !("def" in schema) || schema.constructor.name !== "ZodObject" && schema.def.type !== "object") return [];
|
|
327
|
-
const zodObject = schema;
|
|
328
|
-
return Object.entries(zodObject.shape).flatMap(([key, value]) => {
|
|
329
|
-
return traverseKey({
|
|
330
|
-
key,
|
|
331
|
-
value,
|
|
332
|
-
messages,
|
|
333
|
-
enums,
|
|
334
|
-
isOptional: false,
|
|
335
|
-
isInArray: false,
|
|
336
|
-
typePrefix,
|
|
337
|
-
parentKey
|
|
338
|
-
});
|
|
339
|
-
}).map((field, index) => `${protobufFieldToType({ field })} ${field.name} = ${index + 1};`);
|
|
340
|
-
};
|
|
341
|
-
|
|
342
|
-
//#endregion
|
|
343
|
-
//#region src/service-generator.ts
|
|
344
|
-
/**
|
|
345
|
-
* Parses a Zod service schema and extracts method definitions.
|
|
346
|
-
* Each method must be a function with one argument (request) and a return value (response).
|
|
347
|
-
*
|
|
348
|
-
* @param name - Service name
|
|
349
|
-
* @param schema - Zod object containing service methods as functions
|
|
350
|
-
* @returns Service definition with extracted methods
|
|
351
|
-
*/
|
|
352
|
-
const parseZodServiceSchema = (name, schema) => {
|
|
353
|
-
const shape = schema.shape;
|
|
354
|
-
const methods = [];
|
|
355
|
-
for (const [methodName, methodSchema] of Object.entries(shape)) {
|
|
356
|
-
const methodDef = methodSchema.def;
|
|
357
|
-
if (methodDef.type === "function") {
|
|
358
|
-
const args = (methodDef.input?.def)?.items ?? [];
|
|
359
|
-
const output = methodDef.output;
|
|
360
|
-
if (args.length > 0 && args[0] && output) {
|
|
361
|
-
const request = args[0];
|
|
362
|
-
const response = output;
|
|
363
|
-
let streaming;
|
|
364
|
-
streaming = methodSchema.meta()?.streaming;
|
|
365
|
-
methods.push({
|
|
366
|
-
name: methodName,
|
|
367
|
-
request,
|
|
368
|
-
response,
|
|
369
|
-
streaming
|
|
370
|
-
});
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
return {
|
|
375
|
-
name,
|
|
376
|
-
methods
|
|
377
|
-
};
|
|
378
|
-
};
|
|
379
|
-
/**
|
|
380
|
-
* Normalizes service input data into an array of service definitions.
|
|
381
|
-
* If an array is passed, returns it as is.
|
|
382
|
-
* If an object is passed, converts each key-value pair into a service definition.
|
|
383
|
-
*
|
|
384
|
-
* @param services - Array of service definitions or object with Zod schemas
|
|
385
|
-
* @returns Array of normalized service definitions
|
|
386
|
-
*/
|
|
387
|
-
const normalizeServices = (services) => {
|
|
388
|
-
if (Array.isArray(services)) return services;
|
|
389
|
-
return Object.entries(services).map(([name, schema]) => parseZodServiceSchema(name, schema));
|
|
390
|
-
};
|
|
391
|
-
/**
|
|
392
|
-
* Ensures that the schema is a ZodObject.
|
|
393
|
-
* If the schema is already an object, returns it as is.
|
|
394
|
-
* Otherwise, wraps the schema in an object with a "data" field.
|
|
395
|
-
*
|
|
396
|
-
* @param schema - Zod schema of any type
|
|
397
|
-
* @returns ZodObject containing the original schema
|
|
398
|
-
*/
|
|
399
|
-
const ensureZodObject = (schema) => {
|
|
400
|
-
if ((schema.def.type || schema.constructor.name) === "object" || schema.constructor.name === "ZodObject") return schema;
|
|
401
|
-
return zod.z.object({ data: schema });
|
|
402
|
-
};
|
|
403
|
-
/**
|
|
404
|
-
* Generates the name for a request message based on the method name.
|
|
405
|
-
*
|
|
406
|
-
* @param methodName - Name of the service method
|
|
407
|
-
* @param typePrefix - Optional prefix for type names
|
|
408
|
-
* @returns Generated request message name in PascalCase
|
|
409
|
-
*/
|
|
410
|
-
const generateRequestMessageName = (methodName, typePrefix) => {
|
|
411
|
-
const messageName = toPascalCase({ value: `${methodName}Request` });
|
|
412
|
-
return typePrefix ? `${typePrefix}${messageName}` : messageName;
|
|
413
|
-
};
|
|
414
|
-
/**
|
|
415
|
-
* Generates the name for a response message based on the method name.
|
|
416
|
-
*
|
|
417
|
-
* @param methodName - Name of the service method
|
|
418
|
-
* @param typePrefix - Optional prefix for type names
|
|
419
|
-
* @returns Generated response message name in PascalCase
|
|
420
|
-
*/
|
|
421
|
-
const generateResponseMessageName = (methodName, typePrefix) => {
|
|
422
|
-
const messageName = toPascalCase({ value: `${methodName}Response` });
|
|
423
|
-
return typePrefix ? `${typePrefix}${messageName}` : messageName;
|
|
424
|
-
};
|
|
425
|
-
/**
|
|
426
|
-
* Processes a service method by generating request and response message names
|
|
427
|
-
* and traversing their schemas to populate the context with message definitions.
|
|
428
|
-
*
|
|
429
|
-
* @param method - Service method definition
|
|
430
|
-
* @param context - Generation context containing messages, enums, and type prefix
|
|
431
|
-
* @returns Object containing request and response message names
|
|
432
|
-
*/
|
|
433
|
-
const processServiceMethod = (method, context) => {
|
|
434
|
-
const { messages, enums, typePrefix } = context;
|
|
435
|
-
const requestName = generateRequestMessageName(method.name, typePrefix);
|
|
436
|
-
const responseName = generateResponseMessageName(method.name, typePrefix);
|
|
437
|
-
if (!messages.has(requestName)) {
|
|
438
|
-
const requestFields = traverseSchema({
|
|
439
|
-
schema: ensureZodObject(method.request),
|
|
440
|
-
messages,
|
|
441
|
-
enums,
|
|
442
|
-
typePrefix,
|
|
443
|
-
parentKey: requestName
|
|
444
|
-
});
|
|
445
|
-
messages.set(requestName, requestFields);
|
|
446
|
-
}
|
|
447
|
-
if (!messages.has(responseName)) {
|
|
448
|
-
const responseFields = traverseSchema({
|
|
449
|
-
schema: ensureZodObject(method.response),
|
|
450
|
-
messages,
|
|
451
|
-
enums,
|
|
452
|
-
typePrefix,
|
|
453
|
-
parentKey: responseName
|
|
454
|
-
});
|
|
455
|
-
messages.set(responseName, responseFields);
|
|
456
|
-
}
|
|
457
|
-
return {
|
|
458
|
-
requestName,
|
|
459
|
-
responseName
|
|
460
|
-
};
|
|
461
|
-
};
|
|
462
|
-
/**
|
|
463
|
-
* Generates protobuf service definitions from Zod service schemas.
|
|
464
|
-
* Supports streaming methods (client, server, bidirectional).
|
|
465
|
-
*
|
|
466
|
-
* @param services - Service definitions as array or object with Zod schemas
|
|
467
|
-
* @param context - Generation context containing messages, enums, and type prefix
|
|
468
|
-
* @returns Array of protobuf service definition strings
|
|
469
|
-
*/
|
|
470
|
-
const generateServices = (services, context) => {
|
|
471
|
-
return normalizeServices(services).map((service) => {
|
|
472
|
-
const methods = service.methods.map((method) => {
|
|
473
|
-
const { requestName, responseName } = processServiceMethod(method, context);
|
|
474
|
-
const requestStreaming = method.streaming === "client" || method.streaming === "bidirectional";
|
|
475
|
-
const responseStreaming = method.streaming === "server" || method.streaming === "bidirectional";
|
|
476
|
-
const requestType = requestStreaming ? `stream ${requestName}` : requestName;
|
|
477
|
-
const responseType = responseStreaming ? `stream ${responseName}` : responseName;
|
|
478
|
-
return ` rpc ${toPascalCase({ value: method.name })}(${requestType}) returns (${responseType});`;
|
|
479
|
-
});
|
|
480
|
-
return `service ${toPascalCase({ value: service.name })} {\n${methods.join("\n")}\n}`;
|
|
481
|
-
});
|
|
482
|
-
};
|
|
483
|
-
|
|
484
|
-
//#endregion
|
|
485
|
-
//#region src/zod-to-protobuf.ts
|
|
486
|
-
/**
|
|
487
|
-
* Generates a protobuf definition string for services only (without root message).
|
|
488
|
-
* Convenience function that calls zodToProtobuf with an empty schema.
|
|
489
|
-
*
|
|
490
|
-
* @param options - Options for protobuf generation
|
|
491
|
-
* @returns Protobuf definition string
|
|
492
|
-
*/
|
|
493
|
-
const zodToProtobufService = (options = {}) => {
|
|
494
|
-
return zodToProtobuf(zod.z.object(), options);
|
|
495
|
-
};
|
|
496
|
-
/**
|
|
497
|
-
* Converts a Zod schema to a protobuf definition string.
|
|
498
|
-
* Generates messages, enums, and services based on the provided schema and options.
|
|
499
|
-
*
|
|
500
|
-
* @param schema - Optional Zod schema to convert (if not provided, only services will be generated)
|
|
501
|
-
* @param options - Options for protobuf generation including package name, root message name, type prefix, and services
|
|
502
|
-
* @returns Complete protobuf definition string
|
|
503
|
-
*/
|
|
504
|
-
const zodToProtobuf = (schema, options = {}) => {
|
|
505
|
-
const { packageName = "default", rootMessageName = "Message", typePrefix = "", services, skipRootMessage = false } = options;
|
|
506
|
-
const messages = /* @__PURE__ */ new Map();
|
|
507
|
-
const enums = /* @__PURE__ */ new Map();
|
|
508
|
-
if (schema && !skipRootMessage) {
|
|
509
|
-
const fields = traverseSchema({
|
|
510
|
-
schema,
|
|
511
|
-
messages,
|
|
512
|
-
enums,
|
|
513
|
-
typePrefix
|
|
514
|
-
});
|
|
515
|
-
if (fields.length > 0) {
|
|
516
|
-
const rootMessageKey = `${typePrefix}${rootMessageName}`;
|
|
517
|
-
messages.set(rootMessageKey, fields);
|
|
518
|
-
}
|
|
519
|
-
}
|
|
520
|
-
const context = {
|
|
521
|
-
messages,
|
|
522
|
-
enums,
|
|
523
|
-
typePrefix: typePrefix || null
|
|
524
|
-
};
|
|
525
|
-
const content = [
|
|
526
|
-
services && (Array.isArray(services) ? services.length > 0 : Object.keys(services).length > 0) ? generateServices(services, context) : [],
|
|
527
|
-
Array.from(enums.values()).map((enumDef) => enumDef.join("\n")),
|
|
528
|
-
Array.from(messages.entries()).map(([name, fields]) => `message ${name} {\n${fields.map((field) => ` ${field}`).join("\n")}\n}`)
|
|
529
|
-
].filter((strings) => !!strings.length).map((strings) => strings.join("\n\n")).join("\n\n");
|
|
530
|
-
let protoDefinition = "";
|
|
531
|
-
if (options.warningDeclaration !== false) protoDefinition += `
|
|
532
|
-
/**
|
|
533
|
-
* This file was automatically generated by zod-to-proto.
|
|
534
|
-
* DO NOT MODIFY IT BY HAND. Instead, modify the source Zod schema.
|
|
535
|
-
*/
|
|
536
|
-
`;
|
|
537
|
-
protoDefinition += `
|
|
538
|
-
syntax = "proto3";
|
|
539
|
-
package ${packageName};
|
|
540
|
-
|
|
541
|
-
${content}
|
|
542
|
-
`;
|
|
543
|
-
return protoDefinition.trim();
|
|
544
|
-
};
|
|
545
|
-
|
|
546
|
-
//#endregion
|
|
547
|
-
exports.zodToProtobuf = zodToProtobuf;
|
|
548
|
-
exports.zodToProtobufService = zodToProtobufService;
|
|
549
|
-
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["ZodArray","ZodSet","ZodObject","ZodOptional","ZodNullable","ZodMap","ZodRecord","ZodString","ZodNumber","ZodBoolean","ZodEnum","ZodDate","ZodBigInt","ZodType","ZodTuple","tupleFields: ProtobufField[]","methods: ServiceMethod[]","streaming: \"client\" | \"server\" | \"bidirectional\" | undefined","z","z","protoDefinition: string"],"sources":["../src/utils.ts","../src/traversers.ts","../src/service-generator.ts","../src/zod-to-protobuf.ts"],"sourcesContent":["import { ZodNumber } from \"zod\";\nimport type { ProtobufField } from \"./types\";\n\n/**\n * Determines the protobuf number type name based on Zod number schema.\n * Returns \"int32\" for integers, \"double\" for floating point numbers.\n *\n * @param value - Zod number schema\n * @returns Protobuf number type name (\"int32\" or \"double\")\n */\nexport const getNumberTypeName = ({ value }: { value: ZodNumber }): string => {\n return value.isInt ? \"int32\" : \"double\";\n};\n\n/**\n * Converts a string to PascalCase format.\n * Handles dot-separated strings by capitalizing each part.\n *\n * @param value - String to convert\n * @returns PascalCase string\n */\nexport const toPascalCase = ({ value }: { value: string }): string => {\n return value\n .split(\".\")\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join(\"\");\n};\n\n/**\n * Converts a protobuf field definition to its type string representation.\n * Filters out null/empty values and joins the remaining types.\n *\n * @param field - Protobuf field definition\n * @returns Type string for the protobuf field\n */\nexport const protobufFieldToType = ({\n field,\n}: {\n field: ProtobufField;\n}): string => {\n return field.types.filter(Boolean).join(\" \");\n};\n","import * as inflection from \"inflection\";\nimport {\n ZodArray,\n ZodBigInt,\n ZodBoolean,\n ZodDate,\n ZodEnum,\n ZodMap,\n ZodNullable,\n ZodNumber,\n ZodObject,\n ZodOptional,\n ZodRecord,\n ZodSet,\n ZodString,\n ZodTuple,\n ZodType,\n type ZodTypeAny,\n} from \"zod\";\nimport {\n ZodArrayDefinition,\n ZodMapDefinition,\n ZodRecordDefinition,\n type ProtobufField,\n} from \"./types\";\nimport { getNumberTypeName, toPascalCase, protobufFieldToType } from \"./utils\";\n\n/**\n * Traverses a Zod array or set schema and converts it to protobuf repeated fields.\n * Handles nested types and generates appropriate field definitions.\n *\n * @param key - Field name\n * @param value - Zod array or set schema\n * @param messages - Map of message names to their protobuf fields\n * @param enums - Map of enum names to their protobuf values\n * @param typePrefix - Optional prefix for type names\n * @param parentKey - Optional parent message name for nested types\n * @returns Array of protobuf field definitions\n */\nexport const traverseArray = ({\n key,\n value,\n messages,\n enums,\n typePrefix,\n parentKey,\n}: {\n key: string;\n value: ZodArray<ZodTypeAny> | ZodSet<ZodTypeAny>;\n messages: Map<string, string[]>;\n enums: Map<string, string[]>;\n typePrefix: string | null;\n parentKey?: string;\n}): ProtobufField[] => {\n const nestedValue =\n value instanceof ZodArray\n ? value.element\n : value instanceof ZodSet\n ? (value.def as unknown as ZodArrayDefinition).valueType\n : // @ts-expect-error\n (value.def as unknown as ZodArrayDefinition).element;\n\n const singularKey = inflection.singularize(key);\n const elementFields = traverseKey({\n key: singularKey,\n value: nestedValue,\n messages,\n enums,\n isOptional: false,\n isInArray: true,\n typePrefix,\n parentKey: nestedValue instanceof ZodObject ? parentKey : undefined,\n });\n return elementFields.map((field) => ({\n ...field,\n types: [\"repeated\", ...field.types],\n name: field.name.replace(singularKey, key),\n }));\n};\n\n/**\n * Traverses a Zod map schema and converts it to a protobuf map type.\n * Validates that both key and value types are simple types suitable for map keys/values.\n *\n * @param key - Field name\n * @param value - Zod map schema\n * @param messages - Map of message names to their protobuf fields\n * @param enums - Map of enum names to their protobuf values\n * @param typePrefix - Optional prefix for type names\n * @param parentKey - Optional parent message name for nested types\n * @returns Array containing a single protobuf map field definition, or empty array if invalid\n */\nexport const traverseMap = ({\n key,\n value,\n messages,\n enums,\n typePrefix,\n parentKey,\n}: {\n key: string;\n value: ZodMap<ZodTypeAny, ZodTypeAny>;\n messages: Map<string, string[]>;\n enums: Map<string, string[]>;\n typePrefix: string | null;\n parentKey?: string;\n}): ProtobufField[] => {\n const mapDef = value.def as ZodMapDefinition;\n\n const keyType = traverseKey({\n key: inflection.singularize(key),\n value: mapDef.keyType,\n messages,\n enums,\n isOptional: false,\n isInArray: true,\n typePrefix,\n parentKey,\n });\n const valueType = traverseKey({\n key: inflection.singularize(key),\n value: mapDef.valueType,\n messages,\n enums,\n isOptional: false,\n isInArray: true,\n typePrefix,\n parentKey,\n });\n\n if (!keyType[0] || keyType.length !== 1) {\n return [];\n }\n\n if (!valueType[0] || valueType.length !== 1) {\n return [];\n }\n\n const mapType = `map<${protobufFieldToType({ field: keyType[0] })}, ${protobufFieldToType({ field: valueType[0] })}>`;\n return [\n {\n types: [mapType],\n name: key,\n },\n ];\n};\n\n/**\n * Traverses a Zod record schema and converts it to a protobuf map type.\n * Similar to traverseMap but handles ZodRecord type.\n *\n * @param key - Field name\n * @param value - Zod record schema\n * @param messages - Map of message names to their protobuf fields\n * @param enums - Map of enum names to their protobuf values\n * @param typePrefix - Optional prefix for type names\n * @param parentKey - Optional parent message name for nested types\n * @returns Array containing a single protobuf map field definition, or empty array if invalid\n */\nexport const traverseRecord = ({\n key,\n value,\n messages,\n enums,\n typePrefix,\n parentKey,\n}: {\n key: string;\n value: ZodRecord;\n messages: Map<string, string[]>;\n enums: Map<string, string[]>;\n typePrefix: string | null;\n parentKey?: string;\n}): ProtobufField[] => {\n const recordDef = value.def as unknown as ZodRecordDefinition;\n\n const keyType = traverseKey({\n key: inflection.singularize(key),\n value: recordDef.keyType,\n messages,\n enums,\n isOptional: false,\n isInArray: true,\n typePrefix,\n parentKey,\n });\n const valueType = traverseKey({\n key: inflection.singularize(key),\n value: recordDef.valueType,\n messages,\n enums,\n isOptional: false,\n isInArray: true,\n typePrefix,\n parentKey,\n });\n\n if (!keyType[0] || keyType.length !== 1) {\n return [];\n }\n\n if (!valueType[0] || valueType.length !== 1) {\n return [];\n }\n\n const mapType = `map<${protobufFieldToType({ field: keyType[0] })}, ${protobufFieldToType({ field: valueType[0] })}>`;\n return [\n {\n types: [mapType],\n name: key,\n },\n ];\n};\n\n/**\n * Traverses a single key-value pair from a Zod schema and converts it to protobuf field definitions.\n * Handles various Zod types including primitives, objects, arrays, maps, enums, tuples, and optional/nullable fields.\n *\n * @param key - Field name\n * @param value - Zod schema value\n * @param messages - Map of message names to their protobuf fields\n * @param enums - Map of enum names to their protobuf values\n * @param isOptional - Whether the field is optional\n * @param isInArray - Whether the field is inside an array\n * @param typePrefix - Optional prefix for type names\n * @param parentKey - Optional parent message name for nested types\n * @returns Array of protobuf field definitions\n */\nexport const traverseKey = ({\n key,\n value,\n messages,\n enums,\n isOptional,\n isInArray,\n typePrefix,\n parentKey,\n}: {\n key: string;\n value: unknown;\n messages: Map<string, string[]>;\n enums: Map<string, string[]>;\n isOptional: boolean;\n isInArray: boolean;\n typePrefix: string | null;\n parentKey?: string;\n}): ProtobufField[] => {\n if (!value) {\n return [];\n }\n\n if (value instanceof ZodOptional || value instanceof ZodNullable) {\n return traverseKey({\n key,\n value: value.unwrap(),\n messages,\n enums,\n isOptional: true,\n isInArray,\n typePrefix,\n parentKey,\n });\n }\n\n if (value instanceof ZodArray || value instanceof ZodSet) {\n return traverseArray({\n key,\n value: value as ZodArray<ZodTypeAny> | ZodSet<ZodTypeAny>,\n messages,\n enums,\n typePrefix,\n parentKey,\n });\n }\n\n if (value instanceof ZodMap) {\n return traverseMap({\n key,\n value: value as ZodMap<ZodTypeAny, ZodTypeAny>,\n messages,\n enums,\n typePrefix,\n parentKey,\n });\n }\n\n if (value instanceof ZodRecord) {\n return traverseRecord({\n key,\n value: value as ZodRecord,\n messages,\n enums,\n typePrefix,\n parentKey,\n });\n }\n\n const optional = isOptional && !isInArray ? \"optional\" : null;\n\n if (value instanceof ZodObject) {\n let messageName = toPascalCase({ value: key });\n if (parentKey) {\n const isParentAlreadyPascalCase = /^[A-Z][a-zA-Z0-9]*$/.test(parentKey);\n if (isParentAlreadyPascalCase) {\n messageName = `${parentKey}${messageName}`;\n } else {\n const parentMessageName = toPascalCase({ value: parentKey });\n messageName = `${parentMessageName}${messageName}`;\n }\n }\n if (typePrefix) {\n messageName = `${typePrefix}${messageName}`;\n }\n const nestedMessageFields = traverseSchema({\n schema: value,\n messages,\n enums,\n typePrefix,\n parentKey: messageName,\n });\n messages.set(messageName, nestedMessageFields);\n return [\n {\n types: [optional, messageName],\n name: key,\n },\n ];\n }\n\n if (value instanceof ZodString) {\n return [\n {\n types: [optional, \"string\"],\n name: key,\n },\n ];\n }\n\n if (value instanceof ZodNumber) {\n const typeName = getNumberTypeName({ value });\n return [\n {\n types: [optional, typeName],\n name: key,\n },\n ];\n }\n\n if (value instanceof ZodBoolean) {\n return [\n {\n types: [optional, \"bool\"],\n name: key,\n },\n ];\n }\n\n if (value instanceof ZodEnum) {\n const enumFields = value.options\n .map(\n (option: string | number, index: number) =>\n ` ${String(option)} = ${index};`,\n )\n .join(\"\\n\");\n let enumName = toPascalCase({ value: key });\n if (parentKey) {\n const isParentAlreadyPascalCase = /^[A-Z][a-zA-Z0-9]*$/.test(parentKey);\n if (isParentAlreadyPascalCase) {\n enumName = `${parentKey}${enumName}`;\n } else {\n const parentMessageName = toPascalCase({ value: parentKey });\n enumName = `${parentMessageName}${enumName}`;\n }\n }\n if (typePrefix) {\n enumName = `${typePrefix}${enumName}`;\n }\n enums.set(enumName, [`enum ${enumName} {\\n${enumFields}\\n}`]);\n return [\n {\n types: [optional, enumName],\n name: key,\n },\n ];\n }\n\n if (value instanceof ZodDate) {\n return [\n {\n types: [optional, \"string\"],\n name: key,\n },\n ];\n }\n\n if (value instanceof ZodBigInt) {\n return [\n {\n types: [optional, \"int64\"],\n name: key,\n },\n ];\n }\n\n if (value instanceof ZodType) {\n const def = value.def as {\n type?: string;\n check?: unknown;\n fn?: (data: unknown) => boolean;\n };\n if (def.type === \"custom\" && def.check === \"custom\" && def.fn) {\n try {\n if (\n (typeof Buffer !== \"undefined\" && def.fn(Buffer.alloc(0))) ||\n (typeof Uint8Array !== \"undefined\" && def.fn(new Uint8Array(0)))\n ) {\n return [\n {\n types: [optional, \"bytes\"],\n name: key,\n },\n ];\n }\n } catch {}\n }\n }\n\n if (value instanceof ZodTuple) {\n const tupleFields: ProtobufField[] = (\n value.def.items as ZodTypeAny[]\n ).flatMap((item: ZodTypeAny, index: number) => {\n return traverseKey({\n key: `${key}_${index}`,\n value: item,\n messages,\n enums,\n isOptional: false,\n isInArray,\n typePrefix,\n parentKey,\n });\n });\n\n let tupleMessageName = toPascalCase({ value: key });\n if (parentKey) {\n const isParentAlreadyPascalCase = /^[A-Z][a-zA-Z0-9]*$/.test(parentKey);\n if (isParentAlreadyPascalCase) {\n tupleMessageName = `${parentKey}${tupleMessageName}`;\n } else {\n const parentMessageName = toPascalCase({ value: parentKey });\n tupleMessageName = `${parentMessageName}${tupleMessageName}`;\n }\n }\n if (typePrefix) {\n tupleMessageName = `${typePrefix}${tupleMessageName}`;\n }\n messages.set(\n tupleMessageName,\n tupleFields.map(\n (field, index) =>\n ` ${field.types.join(\" \")} ${field.name} = ${index + 1};`,\n ),\n );\n return [\n {\n types: [optional, tupleMessageName],\n name: key,\n },\n ];\n }\n\n if (value instanceof ZodType) {\n return [];\n }\n\n return [];\n};\n\n/**\n * Traverses a Zod object schema and converts it to protobuf message field definitions.\n * Processes all fields in the schema and generates appropriate protobuf types.\n *\n * @param schema - Zod schema to traverse\n * @param messages - Map of message names to their protobuf fields\n * @param enums - Map of enum names to their protobuf values\n * @param typePrefix - Optional prefix for type names\n * @param parentKey - Optional parent message name for nested types\n * @returns Array of protobuf field definition strings\n */\nexport const traverseSchema = ({\n schema,\n messages,\n enums,\n typePrefix,\n parentKey,\n}: {\n schema: ZodTypeAny;\n messages: Map<string, string[]>;\n enums: Map<string, string[]>;\n typePrefix: string | null;\n parentKey?: string;\n}): string[] => {\n if (\n !schema ||\n typeof schema !== \"object\" ||\n !(\"def\" in schema) ||\n (schema.constructor.name !== \"ZodObject\" &&\n (schema.def as { type?: string }).type !== \"object\")\n ) {\n return [];\n }\n\n const zodObject = schema as ZodObject<any>;\n const fields = Object.entries(zodObject.shape).flatMap(([key, value]) => {\n return traverseKey({\n key,\n value,\n messages,\n enums,\n isOptional: false,\n isInArray: false,\n typePrefix,\n parentKey,\n });\n });\n\n return fields.map(\n (field, index) =>\n `${protobufFieldToType({ field })} ${field.name} = ${index + 1};`,\n );\n};\n","import { z, ZodObject, type ZodTypeAny } from \"zod\";\nimport type {\n ServiceDefinition,\n ServiceMethod,\n ServicesInput,\n ZodFunctionDefinition,\n ZodTupleDefinition,\n} from \"./types\";\nimport { toPascalCase } from \"./utils\";\nimport { traverseSchema } from \"./traversers\";\n\n/**\n * Context for generating protobuf services.\n * Contains accumulated messages, enums, and type prefix.\n */\ninterface ServiceGenerationContext {\n /** Map of message names to their protobuf fields */\n messages: Map<string, string[]>;\n /** Map of enum names to their protobuf values */\n enums: Map<string, string[]>;\n /** Prefix for type names or null if prefix is not used */\n typePrefix: string | null;\n}\n\n/**\n * Parses a Zod service schema and extracts method definitions.\n * Each method must be a function with one argument (request) and a return value (response).\n *\n * @param name - Service name\n * @param schema - Zod object containing service methods as functions\n * @returns Service definition with extracted methods\n */\nconst parseZodServiceSchema = (\n name: string,\n schema: ZodObject<Record<string, ZodTypeAny>>,\n): ServiceDefinition => {\n const shape = schema.shape as Record<string, ZodTypeAny>;\n const methods: ServiceMethod[] = [];\n\n for (const [methodName, methodSchema] of Object.entries(shape)) {\n const methodDef = (methodSchema as ZodTypeAny).def as ZodFunctionDefinition;\n\n if (methodDef.type === \"function\") {\n const inputDef = methodDef.input;\n\n const args = (inputDef?.def as ZodTupleDefinition)?.items ?? [];\n const output = methodDef.output as ZodTypeAny;\n\n if (args.length > 0 && args[0] && output) {\n const request = args[0];\n const response = output;\n\n let streaming: \"client\" | \"server\" | \"bidirectional\" | undefined;\n const metadata = methodSchema.meta();\n streaming = metadata?.streaming as\n | \"client\"\n | \"server\"\n | \"bidirectional\"\n | undefined;\n\n methods.push({\n name: methodName,\n request,\n response,\n streaming,\n });\n }\n }\n }\n\n return {\n name,\n methods,\n };\n};\n\n/**\n * Normalizes service input data into an array of service definitions.\n * If an array is passed, returns it as is.\n * If an object is passed, converts each key-value pair into a service definition.\n *\n * @param services - Array of service definitions or object with Zod schemas\n * @returns Array of normalized service definitions\n */\nconst normalizeServices = (services: ServicesInput): ServiceDefinition[] => {\n if (Array.isArray(services)) {\n return services;\n }\n\n return Object.entries(services).map(([name, schema]) =>\n parseZodServiceSchema(name, schema),\n );\n};\n\n/**\n * Ensures that the schema is a ZodObject.\n * If the schema is already an object, returns it as is.\n * Otherwise, wraps the schema in an object with a \"data\" field.\n *\n * @param schema - Zod schema of any type\n * @returns ZodObject containing the original schema\n */\nconst ensureZodObject = (\n schema: ZodTypeAny,\n): ZodObject<Record<string, ZodTypeAny>> => {\n const schemaType =\n (schema.def as { type?: string }).type || schema.constructor.name;\n\n if (schemaType === \"object\" || schema.constructor.name === \"ZodObject\") {\n return schema as ZodObject<Record<string, ZodTypeAny>>;\n }\n\n return z.object({\n data: schema,\n });\n};\n\n/**\n * Generates the name for a request message based on the method name.\n *\n * @param methodName - Name of the service method\n * @param typePrefix - Optional prefix for type names\n * @returns Generated request message name in PascalCase\n */\nconst generateRequestMessageName = (\n methodName: string,\n typePrefix: string | null,\n): string => {\n const messageName = toPascalCase({ value: `${methodName}Request` });\n return typePrefix ? `${typePrefix}${messageName}` : messageName;\n};\n\n/**\n * Generates the name for a response message based on the method name.\n *\n * @param methodName - Name of the service method\n * @param typePrefix - Optional prefix for type names\n * @returns Generated response message name in PascalCase\n */\nconst generateResponseMessageName = (\n methodName: string,\n typePrefix: string | null,\n): string => {\n const messageName = toPascalCase({ value: `${methodName}Response` });\n return typePrefix ? `${typePrefix}${messageName}` : messageName;\n};\n\n/**\n * Processes a service method by generating request and response message names\n * and traversing their schemas to populate the context with message definitions.\n *\n * @param method - Service method definition\n * @param context - Generation context containing messages, enums, and type prefix\n * @returns Object containing request and response message names\n */\nconst processServiceMethod = (\n method: ServiceMethod,\n context: ServiceGenerationContext,\n): { requestName: string; responseName: string } => {\n const { messages, enums, typePrefix } = context;\n\n const requestName = generateRequestMessageName(method.name, typePrefix);\n const responseName = generateResponseMessageName(method.name, typePrefix);\n\n if (!messages.has(requestName)) {\n const requestSchema = ensureZodObject(method.request);\n const requestFields = traverseSchema({\n schema: requestSchema,\n messages,\n enums,\n typePrefix,\n parentKey: requestName,\n });\n messages.set(requestName, requestFields);\n }\n\n if (!messages.has(responseName)) {\n const responseSchema = ensureZodObject(method.response);\n const responseFields = traverseSchema({\n schema: responseSchema,\n messages,\n enums,\n typePrefix,\n parentKey: responseName,\n });\n messages.set(responseName, responseFields);\n }\n\n return { requestName, responseName };\n};\n\n/**\n * Generates protobuf service definitions from Zod service schemas.\n * Supports streaming methods (client, server, bidirectional).\n *\n * @param services - Service definitions as array or object with Zod schemas\n * @param context - Generation context containing messages, enums, and type prefix\n * @returns Array of protobuf service definition strings\n */\nexport const generateServices = (\n services: ServicesInput,\n context: ServiceGenerationContext,\n): string[] => {\n const normalizedServices = normalizeServices(services);\n\n return normalizedServices.map((service) => {\n const methods = service.methods.map((method) => {\n const { requestName, responseName } = processServiceMethod(\n method,\n context,\n );\n\n const requestStreaming =\n method.streaming === \"client\" || method.streaming === \"bidirectional\";\n const responseStreaming =\n method.streaming === \"server\" || method.streaming === \"bidirectional\";\n\n const requestType = requestStreaming\n ? `stream ${requestName}`\n : requestName;\n const responseType = responseStreaming\n ? `stream ${responseName}`\n : responseName;\n\n return ` rpc ${toPascalCase({ value: method.name })}(${requestType}) returns (${responseType});`;\n });\n\n return `service ${toPascalCase({ value: service.name })} {\\n${methods.join(\"\\n\")}\\n}`;\n });\n};\n","import type { ZodTypeAny } from \"zod\";\nimport type { ZodToProtobufOptions } from \"./types\";\nimport { traverseSchema } from \"./traversers\";\nimport { generateServices } from \"./service-generator\";\nimport { z } from \"zod\";\n\n/**\n * Generates a protobuf definition string for services only (without root message).\n * Convenience function that calls zodToProtobuf with an empty schema.\n *\n * @param options - Options for protobuf generation\n * @returns Protobuf definition string\n */\nexport const zodToProtobufService = (\n options: ZodToProtobufOptions = {},\n): string => {\n return zodToProtobuf(z.object(), options);\n};\n\n/**\n * Converts a Zod schema to a protobuf definition string.\n * Generates messages, enums, and services based on the provided schema and options.\n *\n * @param schema - Optional Zod schema to convert (if not provided, only services will be generated)\n * @param options - Options for protobuf generation including package name, root message name, type prefix, and services\n * @returns Complete protobuf definition string\n */\nexport const zodToProtobuf = (\n schema?: ZodTypeAny,\n options: ZodToProtobufOptions = {},\n): string => {\n const {\n packageName = \"default\",\n rootMessageName = \"Message\",\n typePrefix = \"\",\n services,\n skipRootMessage = false,\n } = options;\n\n const messages = new Map<string, string[]>();\n const enums = new Map<string, string[]>();\n\n if (schema && !skipRootMessage) {\n const fields = traverseSchema({ schema, messages, enums, typePrefix });\n if (fields.length > 0) {\n const rootMessageKey = `${typePrefix}${rootMessageName}`;\n messages.set(rootMessageKey, fields);\n }\n }\n\n const context = {\n messages,\n enums,\n typePrefix: typePrefix || null,\n };\n\n const hasServices =\n services &&\n (Array.isArray(services)\n ? services.length > 0\n : Object.keys(services).length > 0);\n\n const servicesString = hasServices ? generateServices(services, context) : [];\n\n const enumsString = Array.from(enums.values()).map((enumDef) =>\n enumDef.join(\"\\n\"),\n );\n\n const messagesString = Array.from(messages.entries()).map(\n ([name, fields]) =>\n `message ${name} {\\n${fields.map((field) => ` ${field}`).join(\"\\n\")}\\n}`,\n );\n\n const content = [servicesString, enumsString, messagesString]\n .filter((strings) => !!strings.length)\n .map((strings) => strings.join(\"\\n\\n\"))\n .join(\"\\n\\n\");\n\n let protoDefinition: string = \"\";\n if (options.warningDeclaration !== false) {\n protoDefinition += `\n/**\n * This file was automatically generated by zod-to-proto.\n * DO NOT MODIFY IT BY HAND. Instead, modify the source Zod schema.\n */\n`;\n }\n\n protoDefinition += `\nsyntax = \"proto3\";\npackage ${packageName};\n\n${content}\n`;\n\n return protoDefinition.trim();\n};\n"],"mappings":"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"}
|
package/dist/index.d.cts
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import { ZodObject, ZodTypeAny } from "zod";
|
|
2
|
-
|
|
3
|
-
//#region src/types.d.ts
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Input type for service definitions.
|
|
7
|
-
* Can be either an array of service definitions or an object mapping service names to Zod schemas.
|
|
8
|
-
*/
|
|
9
|
-
type ServicesInput = ServiceDefinition[] | Record<string, ZodObject<any>>;
|
|
10
|
-
/**
|
|
11
|
-
* Options for converting Zod schemas to protobuf definitions.
|
|
12
|
-
*/
|
|
13
|
-
interface ZodToProtobufOptions {
|
|
14
|
-
/** Whether to add the warning declaration to the protobuf definition */
|
|
15
|
-
warningDeclaration?: boolean;
|
|
16
|
-
/** Package name for the generated protobuf file */
|
|
17
|
-
packageName?: string;
|
|
18
|
-
/** Name of the root message (default: "Message") */
|
|
19
|
-
rootMessageName?: string;
|
|
20
|
-
/** Prefix to add to all generated type names */
|
|
21
|
-
typePrefix?: string;
|
|
22
|
-
/** Service definitions to include in the protobuf output */
|
|
23
|
-
services?: ServicesInput;
|
|
24
|
-
/** Whether to skip generating the root message */
|
|
25
|
-
skipRootMessage?: boolean;
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* Definition of a single service method.
|
|
29
|
-
*/
|
|
30
|
-
interface ServiceMethod {
|
|
31
|
-
/** Method name */
|
|
32
|
-
name: string;
|
|
33
|
-
/** Zod schema for the request message */
|
|
34
|
-
request: ZodTypeAny;
|
|
35
|
-
/** Zod schema for the response message */
|
|
36
|
-
response: ZodTypeAny;
|
|
37
|
-
/** Streaming type: "client" for client streaming, "server" for server streaming, "bidirectional" for both */
|
|
38
|
-
streaming?: "client" | "server" | "bidirectional";
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Definition of a protobuf service containing multiple methods.
|
|
42
|
-
*/
|
|
43
|
-
interface ServiceDefinition {
|
|
44
|
-
/** Service name */
|
|
45
|
-
name: string;
|
|
46
|
-
/** Array of service methods */
|
|
47
|
-
methods: ServiceMethod[];
|
|
48
|
-
}
|
|
49
|
-
//#endregion
|
|
50
|
-
//#region src/zod-to-protobuf.d.ts
|
|
51
|
-
/**
|
|
52
|
-
* Generates a protobuf definition string for services only (without root message).
|
|
53
|
-
* Convenience function that calls zodToProtobuf with an empty schema.
|
|
54
|
-
*
|
|
55
|
-
* @param options - Options for protobuf generation
|
|
56
|
-
* @returns Protobuf definition string
|
|
57
|
-
*/
|
|
58
|
-
declare const zodToProtobufService: (options?: ZodToProtobufOptions) => string;
|
|
59
|
-
/**
|
|
60
|
-
* Converts a Zod schema to a protobuf definition string.
|
|
61
|
-
* Generates messages, enums, and services based on the provided schema and options.
|
|
62
|
-
*
|
|
63
|
-
* @param schema - Optional Zod schema to convert (if not provided, only services will be generated)
|
|
64
|
-
* @param options - Options for protobuf generation including package name, root message name, type prefix, and services
|
|
65
|
-
* @returns Complete protobuf definition string
|
|
66
|
-
*/
|
|
67
|
-
declare const zodToProtobuf: (schema?: ZodTypeAny, options?: ZodToProtobufOptions) => string;
|
|
68
|
-
//#endregion
|
|
69
|
-
export { zodToProtobuf, zodToProtobufService };
|
|
70
|
-
//# sourceMappingURL=index.d.cts.map
|