@globalart/zod-to-proto 1.0.14 → 1.0.15

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.cjs CHANGED
@@ -26,18 +26,51 @@ inflection = __toESM(inflection);
26
26
  let zod = require("zod");
27
27
 
28
28
  //#region src/utils.ts
29
+ /**
30
+ * Determines the protobuf number type name based on Zod number schema.
31
+ * Returns "int32" for integers, "double" for floating point numbers.
32
+ *
33
+ * @param value - Zod number schema
34
+ * @returns Protobuf number type name ("int32" or "double")
35
+ */
29
36
  const getNumberTypeName = ({ value }) => {
30
37
  return value.isInt ? "int32" : "double";
31
38
  };
39
+ /**
40
+ * Converts a string to PascalCase format.
41
+ * Handles dot-separated strings by capitalizing each part.
42
+ *
43
+ * @param value - String to convert
44
+ * @returns PascalCase string
45
+ */
32
46
  const toPascalCase = ({ value }) => {
33
47
  return value.split(".").map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
34
48
  };
49
+ /**
50
+ * Converts a protobuf field definition to its type string representation.
51
+ * Filters out null/empty values and joins the remaining types.
52
+ *
53
+ * @param field - Protobuf field definition
54
+ * @returns Type string for the protobuf field
55
+ */
35
56
  const protobufFieldToType = ({ field }) => {
36
57
  return field.types.filter(Boolean).join(" ");
37
58
  };
38
59
 
39
60
  //#endregion
40
61
  //#region src/traversers.ts
62
+ /**
63
+ * Traverses a Zod array or set schema and converts it to protobuf repeated fields.
64
+ * Handles nested types and generates appropriate field definitions.
65
+ *
66
+ * @param key - Field name
67
+ * @param value - Zod array or set schema
68
+ * @param messages - Map of message names to their protobuf fields
69
+ * @param enums - Map of enum names to their protobuf values
70
+ * @param typePrefix - Optional prefix for type names
71
+ * @param parentKey - Optional parent message name for nested types
72
+ * @returns Array of protobuf field definitions
73
+ */
41
74
  const traverseArray = ({ key, value, messages, enums, typePrefix, parentKey }) => {
42
75
  const nestedValue = value instanceof zod.ZodArray ? value.element : value instanceof zod.ZodSet ? value.def.valueType : value.def.element;
43
76
  const singularKey = inflection.singularize(key);
@@ -56,6 +89,18 @@ const traverseArray = ({ key, value, messages, enums, typePrefix, parentKey }) =
56
89
  name: field.name.replace(singularKey, key)
57
90
  }));
58
91
  };
92
+ /**
93
+ * Traverses a Zod map schema and converts it to a protobuf map type.
94
+ * Validates that both key and value types are simple types suitable for map keys/values.
95
+ *
96
+ * @param key - Field name
97
+ * @param value - Zod map schema
98
+ * @param messages - Map of message names to their protobuf fields
99
+ * @param enums - Map of enum names to their protobuf values
100
+ * @param typePrefix - Optional prefix for type names
101
+ * @param parentKey - Optional parent message name for nested types
102
+ * @returns Array containing a single protobuf map field definition, or empty array if invalid
103
+ */
59
104
  const traverseMap = ({ key, value, messages, enums, typePrefix, parentKey }) => {
60
105
  const mapDef = value.def;
61
106
  const keyType = traverseKey({
@@ -85,6 +130,18 @@ const traverseMap = ({ key, value, messages, enums, typePrefix, parentKey }) =>
85
130
  name: key
86
131
  }];
87
132
  };
133
+ /**
134
+ * Traverses a Zod record schema and converts it to a protobuf map type.
135
+ * Similar to traverseMap but handles ZodRecord type.
136
+ *
137
+ * @param key - Field name
138
+ * @param value - Zod record schema
139
+ * @param messages - Map of message names to their protobuf fields
140
+ * @param enums - Map of enum names to their protobuf values
141
+ * @param typePrefix - Optional prefix for type names
142
+ * @param parentKey - Optional parent message name for nested types
143
+ * @returns Array containing a single protobuf map field definition, or empty array if invalid
144
+ */
88
145
  const traverseRecord = ({ key, value, messages, enums, typePrefix, parentKey }) => {
89
146
  const recordDef = value.def;
90
147
  const keyType = traverseKey({
@@ -114,6 +171,20 @@ const traverseRecord = ({ key, value, messages, enums, typePrefix, parentKey })
114
171
  name: key
115
172
  }];
116
173
  };
174
+ /**
175
+ * Traverses a single key-value pair from a Zod schema and converts it to protobuf field definitions.
176
+ * Handles various Zod types including primitives, objects, arrays, maps, enums, tuples, and optional/nullable fields.
177
+ *
178
+ * @param key - Field name
179
+ * @param value - Zod schema value
180
+ * @param messages - Map of message names to their protobuf fields
181
+ * @param enums - Map of enum names to their protobuf values
182
+ * @param isOptional - Whether the field is optional
183
+ * @param isInArray - Whether the field is inside an array
184
+ * @param typePrefix - Optional prefix for type names
185
+ * @param parentKey - Optional parent message name for nested types
186
+ * @returns Array of protobuf field definitions
187
+ */
117
188
  const traverseKey = ({ key, value, messages, enums, isOptional, isInArray, typePrefix, parentKey }) => {
118
189
  if (!value) return [];
119
190
  if (value instanceof zod.ZodOptional || value instanceof zod.ZodNullable) return traverseKey({
@@ -201,6 +272,15 @@ const traverseKey = ({ key, value, messages, enums, isOptional, isInArray, typeP
201
272
  types: [optional, "int64"],
202
273
  name: key
203
274
  }];
275
+ if (value instanceof zod.ZodType) {
276
+ const def = value.def;
277
+ if (def.type === "custom" && def.check === "custom" && def.fn) try {
278
+ if (typeof Buffer !== "undefined" && def.fn(Buffer.alloc(0)) || typeof Uint8Array !== "undefined" && def.fn(new Uint8Array(0))) return [{
279
+ types: [optional, "bytes"],
280
+ name: key
281
+ }];
282
+ } catch {}
283
+ }
204
284
  if (value instanceof zod.ZodTuple) {
205
285
  const tupleFields = value.def.items.flatMap((item, index) => {
206
286
  return traverseKey({
@@ -227,6 +307,17 @@ const traverseKey = ({ key, value, messages, enums, isOptional, isInArray, typeP
227
307
  if (value instanceof zod.ZodType) return [];
228
308
  return [];
229
309
  };
310
+ /**
311
+ * Traverses a Zod object schema and converts it to protobuf message field definitions.
312
+ * Processes all fields in the schema and generates appropriate protobuf types.
313
+ *
314
+ * @param schema - Zod schema to traverse
315
+ * @param messages - Map of message names to their protobuf fields
316
+ * @param enums - Map of enum names to their protobuf values
317
+ * @param typePrefix - Optional prefix for type names
318
+ * @param parentKey - Optional parent message name for nested types
319
+ * @returns Array of protobuf field definition strings
320
+ */
230
321
  const traverseSchema = ({ schema, messages, enums, typePrefix, parentKey }) => {
231
322
  if (!schema || typeof schema !== "object" || !("def" in schema) || schema.constructor.name !== "ZodObject" && schema.def.type !== "object") return [];
232
323
  const zodObject = schema;
@@ -246,6 +337,14 @@ const traverseSchema = ({ schema, messages, enums, typePrefix, parentKey }) => {
246
337
 
247
338
  //#endregion
248
339
  //#region src/service-generator.ts
340
+ /**
341
+ * Parses a Zod service schema and extracts method definitions.
342
+ * Each method must be a function with one argument (request) and a return value (response).
343
+ *
344
+ * @param name - Service name
345
+ * @param schema - Zod object containing service methods as functions
346
+ * @returns Service definition with extracted methods
347
+ */
249
348
  const parseZodServiceSchema = (name, schema) => {
250
349
  const shape = schema.shape;
251
350
  const methods = [];
@@ -270,22 +369,60 @@ const parseZodServiceSchema = (name, schema) => {
270
369
  methods
271
370
  };
272
371
  };
372
+ /**
373
+ * Normalizes service input data into an array of service definitions.
374
+ * If an array is passed, returns it as is.
375
+ * If an object is passed, converts each key-value pair into a service definition.
376
+ *
377
+ * @param services - Array of service definitions or object with Zod schemas
378
+ * @returns Array of normalized service definitions
379
+ */
273
380
  const normalizeServices = (services) => {
274
381
  if (Array.isArray(services)) return services;
275
382
  return Object.entries(services).map(([name, schema]) => parseZodServiceSchema(name, schema));
276
383
  };
384
+ /**
385
+ * Ensures that the schema is a ZodObject.
386
+ * If the schema is already an object, returns it as is.
387
+ * Otherwise, wraps the schema in an object with a "data" field.
388
+ *
389
+ * @param schema - Zod schema of any type
390
+ * @returns ZodObject containing the original schema
391
+ */
277
392
  const ensureZodObject = (schema) => {
278
393
  if ((schema.def.type || schema.constructor.name) === "object" || schema.constructor.name === "ZodObject") return schema;
279
394
  return zod.z.object({ data: schema });
280
395
  };
396
+ /**
397
+ * Generates the name for a request message based on the method name.
398
+ *
399
+ * @param methodName - Name of the service method
400
+ * @param typePrefix - Optional prefix for type names
401
+ * @returns Generated request message name in PascalCase
402
+ */
281
403
  const generateRequestMessageName = (methodName, typePrefix) => {
282
404
  const messageName = toPascalCase({ value: `${methodName}Request` });
283
405
  return typePrefix ? `${typePrefix}${messageName}` : messageName;
284
406
  };
407
+ /**
408
+ * Generates the name for a response message based on the method name.
409
+ *
410
+ * @param methodName - Name of the service method
411
+ * @param typePrefix - Optional prefix for type names
412
+ * @returns Generated response message name in PascalCase
413
+ */
285
414
  const generateResponseMessageName = (methodName, typePrefix) => {
286
415
  const messageName = toPascalCase({ value: `${methodName}Response` });
287
416
  return typePrefix ? `${typePrefix}${messageName}` : messageName;
288
417
  };
418
+ /**
419
+ * Processes a service method by generating request and response message names
420
+ * and traversing their schemas to populate the context with message definitions.
421
+ *
422
+ * @param method - Service method definition
423
+ * @param context - Generation context containing messages, enums, and type prefix
424
+ * @returns Object containing request and response message names
425
+ */
289
426
  const processServiceMethod = (method, context) => {
290
427
  const { messages, enums, typePrefix } = context;
291
428
  const requestName = generateRequestMessageName(method.name, typePrefix);
@@ -315,6 +452,14 @@ const processServiceMethod = (method, context) => {
315
452
  responseName
316
453
  };
317
454
  };
455
+ /**
456
+ * Generates protobuf service definitions from Zod service schemas.
457
+ * Supports streaming methods (client, server, bidirectional).
458
+ *
459
+ * @param services - Service definitions as array or object with Zod schemas
460
+ * @param context - Generation context containing messages, enums, and type prefix
461
+ * @returns Array of protobuf service definition strings
462
+ */
318
463
  const generateServices = (services, context) => {
319
464
  return normalizeServices(services).map((service) => {
320
465
  const methods = service.methods.map((method) => {
@@ -331,9 +476,24 @@ const generateServices = (services, context) => {
331
476
 
332
477
  //#endregion
333
478
  //#region src/zod-to-protobuf.ts
479
+ /**
480
+ * Generates a protobuf definition string for services only (without root message).
481
+ * Convenience function that calls zodToProtobuf with an empty schema.
482
+ *
483
+ * @param options - Options for protobuf generation
484
+ * @returns Protobuf definition string
485
+ */
334
486
  const zodToProtobufService = (options = {}) => {
335
487
  return zodToProtobuf(zod.z.object(), options);
336
488
  };
489
+ /**
490
+ * Converts a Zod schema to a protobuf definition string.
491
+ * Generates messages, enums, and services based on the provided schema and options.
492
+ *
493
+ * @param schema - Optional Zod schema to convert (if not provided, only services will be generated)
494
+ * @param options - Options for protobuf generation including package name, root message name, type prefix, and services
495
+ * @returns Complete protobuf definition string
496
+ */
337
497
  const zodToProtobuf = (schema, options = {}) => {
338
498
  const { packageName = "default", rootMessageName = "Message", typePrefix = "", services, skipRootMessage = false } = options;
339
499
  const messages = /* @__PURE__ */ new Map();
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["ZodArray","ZodSet","ZodObject","ZodOptional","ZodNullable","ZodMap","ZodRecord","ZodString","ZodNumber","ZodBoolean","ZodEnum","ZodDate","ZodBigInt","ZodTuple","tupleFields: ProtobufField[]","ZodType","methods: ServiceMethod[]","z","z"],"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\nexport const getNumberTypeName = ({ value }: { value: ZodNumber }): string => {\n return value.isInt ? \"int32\" : \"double\";\n};\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\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\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\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\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\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 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\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\ninterface ServiceGenerationContext {\n messages: Map<string, string[]>;\n enums: Map<string, string[]>;\n typePrefix: string | null;\n}\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 methods.push({\n name: methodName,\n request,\n response,\n });\n }\n }\n }\n\n return {\n name,\n methods,\n };\n};\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\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\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\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\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\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\nexport const zodToProtobufService = (\n options: ZodToProtobufOptions = {}\n): string => {\n return zodToProtobuf(z.object(), options);\n};\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 const 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.cjs","names":["ZodArray","ZodSet","ZodObject","ZodOptional","ZodNullable","ZodMap","ZodRecord","ZodString","ZodNumber","ZodBoolean","ZodEnum","ZodDate","ZodBigInt","ZodType","ZodTuple","tupleFields: ProtobufField[]","methods: ServiceMethod[]","z","z"],"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 methods.push({\n name: methodName,\n request,\n response,\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 const protoDefinition = `\nsyntax = \"proto3\";\npackage ${packageName};\n\n${content}\n`;\n\n return protoDefinition.trim();\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAUA,MAAa,qBAAqB,EAAE,YAA0C;AAC5E,QAAO,MAAM,QAAQ,UAAU;;;;;;;;;AAUjC,MAAa,gBAAgB,EAAE,YAAuC;AACpE,QAAO,MACJ,MAAM,IAAI,CACV,KAAK,SAAS,KAAK,OAAO,EAAE,CAAC,aAAa,GAAG,KAAK,MAAM,EAAE,CAAC,CAC3D,KAAK,GAAG;;;;;;;;;AAUb,MAAa,uBAAuB,EAClC,YAGY;AACZ,QAAO,MAAM,MAAM,OAAO,QAAQ,CAAC,KAAK,IAAI;;;;;;;;;;;;;;;;;ACD9C,MAAa,iBAAiB,EAC5B,KACA,OACA,UACA,OACA,YACA,gBAQqB;CACrB,MAAM,cACJ,iBAAiBA,eACb,MAAM,UACN,iBAAiBC,aACd,MAAM,IAAsC,YAE5C,MAAM,IAAsC;CAErD,MAAM,cAAc,WAAW,YAAY,IAAI;AAW/C,QAVsB,YAAY;EAChC,KAAK;EACL,OAAO;EACP;EACA;EACA,YAAY;EACZ,WAAW;EACX;EACA,WAAW,uBAAuBC,gBAAY,YAAY;EAC3D,CAAC,CACmB,KAAK,WAAW;EACnC,GAAG;EACH,OAAO,CAAC,YAAY,GAAG,MAAM,MAAM;EACnC,MAAM,MAAM,KAAK,QAAQ,aAAa,IAAI;EAC3C,EAAE;;;;;;;;;;;;;;AAeL,MAAa,eAAe,EAC1B,KACA,OACA,UACA,OACA,YACA,gBAQqB;CACrB,MAAM,SAAS,MAAM;CAErB,MAAM,UAAU,YAAY;EAC1B,KAAK,WAAW,YAAY,IAAI;EAChC,OAAO,OAAO;EACd;EACA;EACA,YAAY;EACZ,WAAW;EACX;EACA;EACD,CAAC;CACF,MAAM,YAAY,YAAY;EAC5B,KAAK,WAAW,YAAY,IAAI;EAChC,OAAO,OAAO;EACd;EACA;EACA,YAAY;EACZ,WAAW;EACX;EACA;EACD,CAAC;AAEF,KAAI,CAAC,QAAQ,MAAM,QAAQ,WAAW,EACpC,QAAO,EAAE;AAGX,KAAI,CAAC,UAAU,MAAM,UAAU,WAAW,EACxC,QAAO,EAAE;AAIX,QAAO,CACL;EACE,OAAO,CAHK,OAAO,oBAAoB,EAAE,OAAO,QAAQ,IAAI,CAAC,CAAC,IAAI,oBAAoB,EAAE,OAAO,UAAU,IAAI,CAAC,CAAC,GAG/F;EAChB,MAAM;EACP,CACF;;;;;;;;;;;;;;AAeH,MAAa,kBAAkB,EAC7B,KACA,OACA,UACA,OACA,YACA,gBAQqB;CACrB,MAAM,YAAY,MAAM;CAExB,MAAM,UAAU,YAAY;EAC1B,KAAK,WAAW,YAAY,IAAI;EAChC,OAAO,UAAU;EACjB;EACA;EACA,YAAY;EACZ,WAAW;EACX;EACA;EACD,CAAC;CACF,MAAM,YAAY,YAAY;EAC5B,KAAK,WAAW,YAAY,IAAI;EAChC,OAAO,UAAU;EACjB;EACA;EACA,YAAY;EACZ,WAAW;EACX;EACA;EACD,CAAC;AAEF,KAAI,CAAC,QAAQ,MAAM,QAAQ,WAAW,EACpC,QAAO,EAAE;AAGX,KAAI,CAAC,UAAU,MAAM,UAAU,WAAW,EACxC,QAAO,EAAE;AAIX,QAAO,CACL;EACE,OAAO,CAHK,OAAO,oBAAoB,EAAE,OAAO,QAAQ,IAAI,CAAC,CAAC,IAAI,oBAAoB,EAAE,OAAO,UAAU,IAAI,CAAC,CAAC,GAG/F;EAChB,MAAM;EACP,CACF;;;;;;;;;;;;;;;;AAiBH,MAAa,eAAe,EAC1B,KACA,OACA,UACA,OACA,YACA,WACA,YACA,gBAUqB;AACrB,KAAI,CAAC,MACH,QAAO,EAAE;AAGX,KAAI,iBAAiBC,mBAAe,iBAAiBC,gBACnD,QAAO,YAAY;EACjB;EACA,OAAO,MAAM,QAAQ;EACrB;EACA;EACA,YAAY;EACZ;EACA;EACA;EACD,CAAC;AAGJ,KAAI,iBAAiBJ,gBAAY,iBAAiBC,WAChD,QAAO,cAAc;EACnB;EACO;EACP;EACA;EACA;EACA;EACD,CAAC;AAGJ,KAAI,iBAAiBI,WACnB,QAAO,YAAY;EACjB;EACO;EACP;EACA;EACA;EACA;EACD,CAAC;AAGJ,KAAI,iBAAiBC,cACnB,QAAO,eAAe;EACpB;EACO;EACP;EACA;EACA;EACA;EACD,CAAC;CAGJ,MAAM,WAAW,cAAc,CAAC,YAAY,aAAa;AAEzD,KAAI,iBAAiBJ,eAAW;EAC9B,IAAI,cAAc,aAAa,EAAE,OAAO,KAAK,CAAC;AAC9C,MAAI,UAEF,KADkC,sBAAsB,KAAK,UAAU,CAErE,eAAc,GAAG,YAAY;MAG7B,eAAc,GADY,aAAa,EAAE,OAAO,WAAW,CAAC,GACvB;AAGzC,MAAI,WACF,eAAc,GAAG,aAAa;EAEhC,MAAM,sBAAsB,eAAe;GACzC,QAAQ;GACR;GACA;GACA;GACA,WAAW;GACZ,CAAC;AACF,WAAS,IAAI,aAAa,oBAAoB;AAC9C,SAAO,CACL;GACE,OAAO,CAAC,UAAU,YAAY;GAC9B,MAAM;GACP,CACF;;AAGH,KAAI,iBAAiBK,cACnB,QAAO,CACL;EACE,OAAO,CAAC,UAAU,SAAS;EAC3B,MAAM;EACP,CACF;AAGH,KAAI,iBAAiBC,cAEnB,QAAO,CACL;EACE,OAAO,CAAC,UAHK,kBAAkB,EAAE,OAAO,CAAC,CAGd;EAC3B,MAAM;EACP,CACF;AAGH,KAAI,iBAAiBC,eACnB,QAAO,CACL;EACE,OAAO,CAAC,UAAU,OAAO;EACzB,MAAM;EACP,CACF;AAGH,KAAI,iBAAiBC,aAAS;EAC5B,MAAM,aAAa,MAAM,QACtB,KACE,QAAyB,UACxB,OAAO,OAAO,OAAO,CAAC,KAAK,MAAM,GACpC,CACA,KAAK,KAAK;EACb,IAAI,WAAW,aAAa,EAAE,OAAO,KAAK,CAAC;AAC3C,MAAI,UAEF,KADkC,sBAAsB,KAAK,UAAU,CAErE,YAAW,GAAG,YAAY;MAG1B,YAAW,GADe,aAAa,EAAE,OAAO,WAAW,CAAC,GAC1B;AAGtC,MAAI,WACF,YAAW,GAAG,aAAa;AAE7B,QAAM,IAAI,UAAU,CAAC,QAAQ,SAAS,MAAM,WAAW,KAAK,CAAC;AAC7D,SAAO,CACL;GACE,OAAO,CAAC,UAAU,SAAS;GAC3B,MAAM;GACP,CACF;;AAGH,KAAI,iBAAiBC,YACnB,QAAO,CACL;EACE,OAAO,CAAC,UAAU,SAAS;EAC3B,MAAM;EACP,CACF;AAGH,KAAI,iBAAiBC,cACnB,QAAO,CACL;EACE,OAAO,CAAC,UAAU,QAAQ;EAC1B,MAAM;EACP,CACF;AAGH,KAAI,iBAAiBC,aAAS;EAC5B,MAAM,MAAM,MAAM;AAKlB,MAAI,IAAI,SAAS,YAAY,IAAI,UAAU,YAAY,IAAI,GACzD,KAAI;AACF,OACG,OAAO,WAAW,eAAe,IAAI,GAAG,OAAO,MAAM,EAAE,CAAC,IACxD,OAAO,eAAe,eAAe,IAAI,GAAG,IAAI,WAAW,EAAE,CAAC,CAE/D,QAAO,CACL;IACE,OAAO,CAAC,UAAU,QAAQ;IAC1B,MAAM;IACP,CACF;UAEG;;AAIZ,KAAI,iBAAiBC,cAAU;EAC7B,MAAMC,cACJ,MAAM,IAAI,MACV,SAAS,MAAkB,UAAkB;AAC7C,UAAO,YAAY;IACjB,KAAK,GAAG,IAAI,GAAG;IACf,OAAO;IACP;IACA;IACA,YAAY;IACZ;IACA;IACA;IACD,CAAC;IACF;EAEF,IAAI,mBAAmB,aAAa,EAAE,OAAO,KAAK,CAAC;AACnD,MAAI,UAEF,KADkC,sBAAsB,KAAK,UAAU,CAErE,oBAAmB,GAAG,YAAY;MAGlC,oBAAmB,GADO,aAAa,EAAE,OAAO,WAAW,CAAC,GAClB;AAG9C,MAAI,WACF,oBAAmB,GAAG,aAAa;AAErC,WAAS,IACP,kBACA,YAAY,KACT,OAAO,UACN,KAAK,MAAM,MAAM,KAAK,IAAI,CAAC,GAAG,MAAM,KAAK,KAAK,QAAQ,EAAE,GAC3D,CACF;AACD,SAAO,CACL;GACE,OAAO,CAAC,UAAU,iBAAiB;GACnC,MAAM;GACP,CACF;;AAGH,KAAI,iBAAiBF,YACnB,QAAO,EAAE;AAGX,QAAO,EAAE;;;;;;;;;;;;;AAcX,MAAa,kBAAkB,EAC7B,QACA,UACA,OACA,YACA,gBAOc;AACd,KACE,CAAC,UACD,OAAO,WAAW,YAClB,EAAE,SAAS,WACV,OAAO,YAAY,SAAS,eAC1B,OAAO,IAA0B,SAAS,SAE7C,QAAO,EAAE;CAGX,MAAM,YAAY;AAclB,QAbe,OAAO,QAAQ,UAAU,MAAM,CAAC,SAAS,CAAC,KAAK,WAAW;AACvE,SAAO,YAAY;GACjB;GACA;GACA;GACA;GACA,YAAY;GACZ,WAAW;GACX;GACA;GACD,CAAC;GACF,CAEY,KACX,OAAO,UACN,GAAG,oBAAoB,EAAE,OAAO,CAAC,CAAC,GAAG,MAAM,KAAK,KAAK,QAAQ,EAAE,GAClE;;;;;;;;;;;;;ACjfH,MAAM,yBACJ,MACA,WACsB;CACtB,MAAM,QAAQ,OAAO;CACrB,MAAMG,UAA2B,EAAE;AAEnC,MAAK,MAAM,CAAC,YAAY,iBAAiB,OAAO,QAAQ,MAAM,EAAE;EAC9D,MAAM,YAAa,aAA4B;AAE/C,MAAI,UAAU,SAAS,YAAY;GAGjC,MAAM,QAFW,UAAU,OAEH,MAA4B,SAAS,EAAE;GAC/D,MAAM,SAAS,UAAU;AAEzB,OAAI,KAAK,SAAS,KAAK,KAAK,MAAM,QAAQ;IACxC,MAAM,UAAU,KAAK;IACrB,MAAM,WAAW;AAEjB,YAAQ,KAAK;KACX,MAAM;KACN;KACA;KACD,CAAC;;;;AAKR,QAAO;EACL;EACA;EACD;;;;;;;;;;AAWH,MAAM,qBAAqB,aAAiD;AAC1E,KAAI,MAAM,QAAQ,SAAS,CACzB,QAAO;AAGT,QAAO,OAAO,QAAQ,SAAS,CAAC,KAAK,CAAC,MAAM,YAC1C,sBAAsB,MAAM,OAAO,CACpC;;;;;;;;;;AAWH,MAAM,mBACJ,WAC0C;AAI1C,MAFG,OAAO,IAA0B,QAAQ,OAAO,YAAY,UAE5C,YAAY,OAAO,YAAY,SAAS,YACzD,QAAO;AAGT,QAAOC,MAAE,OAAO,EACd,MAAM,QACP,CAAC;;;;;;;;;AAUJ,MAAM,8BACJ,YACA,eACW;CACX,MAAM,cAAc,aAAa,EAAE,OAAO,GAAG,WAAW,UAAU,CAAC;AACnE,QAAO,aAAa,GAAG,aAAa,gBAAgB;;;;;;;;;AAUtD,MAAM,+BACJ,YACA,eACW;CACX,MAAM,cAAc,aAAa,EAAE,OAAO,GAAG,WAAW,WAAW,CAAC;AACpE,QAAO,aAAa,GAAG,aAAa,gBAAgB;;;;;;;;;;AAWtD,MAAM,wBACJ,QACA,YACkD;CAClD,MAAM,EAAE,UAAU,OAAO,eAAe;CAExC,MAAM,cAAc,2BAA2B,OAAO,MAAM,WAAW;CACvE,MAAM,eAAe,4BAA4B,OAAO,MAAM,WAAW;AAEzE,KAAI,CAAC,SAAS,IAAI,YAAY,EAAE;EAE9B,MAAM,gBAAgB,eAAe;GACnC,QAFoB,gBAAgB,OAAO,QAAQ;GAGnD;GACA;GACA;GACA,WAAW;GACZ,CAAC;AACF,WAAS,IAAI,aAAa,cAAc;;AAG1C,KAAI,CAAC,SAAS,IAAI,aAAa,EAAE;EAE/B,MAAM,iBAAiB,eAAe;GACpC,QAFqB,gBAAgB,OAAO,SAAS;GAGrD;GACA;GACA;GACA,WAAW;GACZ,CAAC;AACF,WAAS,IAAI,cAAc,eAAe;;AAG5C,QAAO;EAAE;EAAa;EAAc;;;;;;;;;;AAWtC,MAAa,oBACX,UACA,YACa;AAGb,QAF2B,kBAAkB,SAAS,CAE5B,KAAK,YAAY;EACzC,MAAM,UAAU,QAAQ,QAAQ,KAAK,WAAW;GAC9C,MAAM,EAAE,aAAa,iBAAiB,qBACpC,QACA,QACD;GAED,MAAM,mBACJ,OAAO,cAAc,YAAY,OAAO,cAAc;GACxD,MAAM,oBACJ,OAAO,cAAc,YAAY,OAAO,cAAc;GAExD,MAAM,cAAc,mBAChB,UAAU,gBACV;GACJ,MAAM,eAAe,oBACjB,UAAU,iBACV;AAEJ,UAAO,WAAW,aAAa,EAAE,OAAO,OAAO,MAAM,CAAC,CAAC,GAAG,YAAY,aAAa,aAAa;IAChG;AAEF,SAAO,WAAW,aAAa,EAAE,OAAO,QAAQ,MAAM,CAAC,CAAC,MAAM,QAAQ,KAAK,KAAK,CAAC;GACjF;;;;;;;;;;;;AC9MJ,MAAa,wBACX,UAAgC,EAAE,KACvB;AACX,QAAO,cAAcC,MAAE,QAAQ,EAAE,QAAQ;;;;;;;;;;AAW3C,MAAa,iBACX,QACA,UAAgC,EAAE,KACvB;CACX,MAAM,EACJ,cAAc,WACd,kBAAkB,WAClB,aAAa,IACb,UACA,kBAAkB,UAChB;CAEJ,MAAM,2BAAW,IAAI,KAAuB;CAC5C,MAAM,wBAAQ,IAAI,KAAuB;AAEzC,KAAI,UAAU,CAAC,iBAAiB;EAC9B,MAAM,SAAS,eAAe;GAAE;GAAQ;GAAU;GAAO;GAAY,CAAC;AACtE,MAAI,OAAO,SAAS,GAAG;GACrB,MAAM,iBAAiB,GAAG,aAAa;AACvC,YAAS,IAAI,gBAAgB,OAAO;;;CAIxC,MAAM,UAAU;EACd;EACA;EACA,YAAY,cAAc;EAC3B;AA+BD,QAPwB;;UAEhB,YAAY;;EAPJ;EAhBd,aACC,MAAM,QAAQ,SAAS,GACpB,SAAS,SAAS,IAClB,OAAO,KAAK,SAAS,CAAC,SAAS,KAEA,iBAAiB,UAAU,QAAQ,GAAG,EAAE;EAEzD,MAAM,KAAK,MAAM,QAAQ,CAAC,CAAC,KAAK,YAClD,QAAQ,KAAK,KAAK,CACnB;EAEsB,MAAM,KAAK,SAAS,SAAS,CAAC,CAAC,KACnD,CAAC,MAAM,YACN,WAAW,KAAK,MAAM,OAAO,KAAK,UAAU,OAAO,QAAQ,CAAC,KAAK,KAAK,CAAC,KAC1E;EAE4D,CAC1D,QAAQ,YAAY,CAAC,CAAC,QAAQ,OAAO,CACrC,KAAK,YAAY,QAAQ,KAAK,OAAO,CAAC,CACtC,KAAK,OAAO,CAMP;EAGe,MAAM"}
package/dist/index.d.cts CHANGED
@@ -1,27 +1,67 @@
1
1
  import { ZodObject, ZodTypeAny } from "zod";
2
2
 
3
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
+ */
4
9
  type ServicesInput = ServiceDefinition[] | Record<string, ZodObject<any>>;
10
+ /**
11
+ * Options for converting Zod schemas to protobuf definitions.
12
+ */
5
13
  interface ZodToProtobufOptions {
14
+ /** Package name for the generated protobuf file */
6
15
  packageName?: string;
16
+ /** Name of the root message (default: "Message") */
7
17
  rootMessageName?: string;
18
+ /** Prefix to add to all generated type names */
8
19
  typePrefix?: string;
20
+ /** Service definitions to include in the protobuf output */
9
21
  services?: ServicesInput;
22
+ /** Whether to skip generating the root message */
10
23
  skipRootMessage?: boolean;
11
24
  }
25
+ /**
26
+ * Definition of a single service method.
27
+ */
12
28
  interface ServiceMethod {
29
+ /** Method name */
13
30
  name: string;
31
+ /** Zod schema for the request message */
14
32
  request: ZodTypeAny;
33
+ /** Zod schema for the response message */
15
34
  response: ZodTypeAny;
35
+ /** Streaming type: "client" for client streaming, "server" for server streaming, "bidirectional" for both */
16
36
  streaming?: "client" | "server" | "bidirectional";
17
37
  }
38
+ /**
39
+ * Definition of a protobuf service containing multiple methods.
40
+ */
18
41
  interface ServiceDefinition {
42
+ /** Service name */
19
43
  name: string;
44
+ /** Array of service methods */
20
45
  methods: ServiceMethod[];
21
46
  }
22
47
  //#endregion
23
48
  //#region src/zod-to-protobuf.d.ts
49
+ /**
50
+ * Generates a protobuf definition string for services only (without root message).
51
+ * Convenience function that calls zodToProtobuf with an empty schema.
52
+ *
53
+ * @param options - Options for protobuf generation
54
+ * @returns Protobuf definition string
55
+ */
24
56
  declare const zodToProtobufService: (options?: ZodToProtobufOptions) => string;
57
+ /**
58
+ * Converts a Zod schema to a protobuf definition string.
59
+ * Generates messages, enums, and services based on the provided schema and options.
60
+ *
61
+ * @param schema - Optional Zod schema to convert (if not provided, only services will be generated)
62
+ * @param options - Options for protobuf generation including package name, root message name, type prefix, and services
63
+ * @returns Complete protobuf definition string
64
+ */
25
65
  declare const zodToProtobuf: (schema?: ZodTypeAny, options?: ZodToProtobufOptions) => string;
26
66
  //#endregion
27
67
  export { zodToProtobuf, zodToProtobufService };
package/dist/index.d.mts CHANGED
@@ -1,27 +1,67 @@
1
1
  import { ZodObject, ZodTypeAny } from "zod";
2
2
 
3
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
+ */
4
9
  type ServicesInput = ServiceDefinition[] | Record<string, ZodObject<any>>;
10
+ /**
11
+ * Options for converting Zod schemas to protobuf definitions.
12
+ */
5
13
  interface ZodToProtobufOptions {
14
+ /** Package name for the generated protobuf file */
6
15
  packageName?: string;
16
+ /** Name of the root message (default: "Message") */
7
17
  rootMessageName?: string;
18
+ /** Prefix to add to all generated type names */
8
19
  typePrefix?: string;
20
+ /** Service definitions to include in the protobuf output */
9
21
  services?: ServicesInput;
22
+ /** Whether to skip generating the root message */
10
23
  skipRootMessage?: boolean;
11
24
  }
25
+ /**
26
+ * Definition of a single service method.
27
+ */
12
28
  interface ServiceMethod {
29
+ /** Method name */
13
30
  name: string;
31
+ /** Zod schema for the request message */
14
32
  request: ZodTypeAny;
33
+ /** Zod schema for the response message */
15
34
  response: ZodTypeAny;
35
+ /** Streaming type: "client" for client streaming, "server" for server streaming, "bidirectional" for both */
16
36
  streaming?: "client" | "server" | "bidirectional";
17
37
  }
38
+ /**
39
+ * Definition of a protobuf service containing multiple methods.
40
+ */
18
41
  interface ServiceDefinition {
42
+ /** Service name */
19
43
  name: string;
44
+ /** Array of service methods */
20
45
  methods: ServiceMethod[];
21
46
  }
22
47
  //#endregion
23
48
  //#region src/zod-to-protobuf.d.ts
49
+ /**
50
+ * Generates a protobuf definition string for services only (without root message).
51
+ * Convenience function that calls zodToProtobuf with an empty schema.
52
+ *
53
+ * @param options - Options for protobuf generation
54
+ * @returns Protobuf definition string
55
+ */
24
56
  declare const zodToProtobufService: (options?: ZodToProtobufOptions) => string;
57
+ /**
58
+ * Converts a Zod schema to a protobuf definition string.
59
+ * Generates messages, enums, and services based on the provided schema and options.
60
+ *
61
+ * @param schema - Optional Zod schema to convert (if not provided, only services will be generated)
62
+ * @param options - Options for protobuf generation including package name, root message name, type prefix, and services
63
+ * @returns Complete protobuf definition string
64
+ */
25
65
  declare const zodToProtobuf: (schema?: ZodTypeAny, options?: ZodToProtobufOptions) => string;
26
66
  //#endregion
27
67
  export { zodToProtobuf, zodToProtobufService };
package/dist/index.mjs CHANGED
@@ -2,18 +2,51 @@ import * as inflection from "inflection";
2
2
  import { ZodArray, ZodBigInt, ZodBoolean, ZodDate, ZodEnum, ZodMap, ZodNullable, ZodNumber, ZodObject, ZodOptional, ZodRecord, ZodSet, ZodString, ZodTuple, ZodType, z } from "zod";
3
3
 
4
4
  //#region src/utils.ts
5
+ /**
6
+ * Determines the protobuf number type name based on Zod number schema.
7
+ * Returns "int32" for integers, "double" for floating point numbers.
8
+ *
9
+ * @param value - Zod number schema
10
+ * @returns Protobuf number type name ("int32" or "double")
11
+ */
5
12
  const getNumberTypeName = ({ value }) => {
6
13
  return value.isInt ? "int32" : "double";
7
14
  };
15
+ /**
16
+ * Converts a string to PascalCase format.
17
+ * Handles dot-separated strings by capitalizing each part.
18
+ *
19
+ * @param value - String to convert
20
+ * @returns PascalCase string
21
+ */
8
22
  const toPascalCase = ({ value }) => {
9
23
  return value.split(".").map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
10
24
  };
25
+ /**
26
+ * Converts a protobuf field definition to its type string representation.
27
+ * Filters out null/empty values and joins the remaining types.
28
+ *
29
+ * @param field - Protobuf field definition
30
+ * @returns Type string for the protobuf field
31
+ */
11
32
  const protobufFieldToType = ({ field }) => {
12
33
  return field.types.filter(Boolean).join(" ");
13
34
  };
14
35
 
15
36
  //#endregion
16
37
  //#region src/traversers.ts
38
+ /**
39
+ * Traverses a Zod array or set schema and converts it to protobuf repeated fields.
40
+ * Handles nested types and generates appropriate field definitions.
41
+ *
42
+ * @param key - Field name
43
+ * @param value - Zod array or set schema
44
+ * @param messages - Map of message names to their protobuf fields
45
+ * @param enums - Map of enum names to their protobuf values
46
+ * @param typePrefix - Optional prefix for type names
47
+ * @param parentKey - Optional parent message name for nested types
48
+ * @returns Array of protobuf field definitions
49
+ */
17
50
  const traverseArray = ({ key, value, messages, enums, typePrefix, parentKey }) => {
18
51
  const nestedValue = value instanceof ZodArray ? value.element : value instanceof ZodSet ? value.def.valueType : value.def.element;
19
52
  const singularKey = inflection.singularize(key);
@@ -32,6 +65,18 @@ const traverseArray = ({ key, value, messages, enums, typePrefix, parentKey }) =
32
65
  name: field.name.replace(singularKey, key)
33
66
  }));
34
67
  };
68
+ /**
69
+ * Traverses a Zod map schema and converts it to a protobuf map type.
70
+ * Validates that both key and value types are simple types suitable for map keys/values.
71
+ *
72
+ * @param key - Field name
73
+ * @param value - Zod map schema
74
+ * @param messages - Map of message names to their protobuf fields
75
+ * @param enums - Map of enum names to their protobuf values
76
+ * @param typePrefix - Optional prefix for type names
77
+ * @param parentKey - Optional parent message name for nested types
78
+ * @returns Array containing a single protobuf map field definition, or empty array if invalid
79
+ */
35
80
  const traverseMap = ({ key, value, messages, enums, typePrefix, parentKey }) => {
36
81
  const mapDef = value.def;
37
82
  const keyType = traverseKey({
@@ -61,6 +106,18 @@ const traverseMap = ({ key, value, messages, enums, typePrefix, parentKey }) =>
61
106
  name: key
62
107
  }];
63
108
  };
109
+ /**
110
+ * Traverses a Zod record schema and converts it to a protobuf map type.
111
+ * Similar to traverseMap but handles ZodRecord type.
112
+ *
113
+ * @param key - Field name
114
+ * @param value - Zod record schema
115
+ * @param messages - Map of message names to their protobuf fields
116
+ * @param enums - Map of enum names to their protobuf values
117
+ * @param typePrefix - Optional prefix for type names
118
+ * @param parentKey - Optional parent message name for nested types
119
+ * @returns Array containing a single protobuf map field definition, or empty array if invalid
120
+ */
64
121
  const traverseRecord = ({ key, value, messages, enums, typePrefix, parentKey }) => {
65
122
  const recordDef = value.def;
66
123
  const keyType = traverseKey({
@@ -90,6 +147,20 @@ const traverseRecord = ({ key, value, messages, enums, typePrefix, parentKey })
90
147
  name: key
91
148
  }];
92
149
  };
150
+ /**
151
+ * Traverses a single key-value pair from a Zod schema and converts it to protobuf field definitions.
152
+ * Handles various Zod types including primitives, objects, arrays, maps, enums, tuples, and optional/nullable fields.
153
+ *
154
+ * @param key - Field name
155
+ * @param value - Zod schema value
156
+ * @param messages - Map of message names to their protobuf fields
157
+ * @param enums - Map of enum names to their protobuf values
158
+ * @param isOptional - Whether the field is optional
159
+ * @param isInArray - Whether the field is inside an array
160
+ * @param typePrefix - Optional prefix for type names
161
+ * @param parentKey - Optional parent message name for nested types
162
+ * @returns Array of protobuf field definitions
163
+ */
93
164
  const traverseKey = ({ key, value, messages, enums, isOptional, isInArray, typePrefix, parentKey }) => {
94
165
  if (!value) return [];
95
166
  if (value instanceof ZodOptional || value instanceof ZodNullable) return traverseKey({
@@ -177,6 +248,15 @@ const traverseKey = ({ key, value, messages, enums, isOptional, isInArray, typeP
177
248
  types: [optional, "int64"],
178
249
  name: key
179
250
  }];
251
+ if (value instanceof ZodType) {
252
+ const def = value.def;
253
+ if (def.type === "custom" && def.check === "custom" && def.fn) try {
254
+ if (typeof Buffer !== "undefined" && def.fn(Buffer.alloc(0)) || typeof Uint8Array !== "undefined" && def.fn(new Uint8Array(0))) return [{
255
+ types: [optional, "bytes"],
256
+ name: key
257
+ }];
258
+ } catch {}
259
+ }
180
260
  if (value instanceof ZodTuple) {
181
261
  const tupleFields = value.def.items.flatMap((item, index) => {
182
262
  return traverseKey({
@@ -203,6 +283,17 @@ const traverseKey = ({ key, value, messages, enums, isOptional, isInArray, typeP
203
283
  if (value instanceof ZodType) return [];
204
284
  return [];
205
285
  };
286
+ /**
287
+ * Traverses a Zod object schema and converts it to protobuf message field definitions.
288
+ * Processes all fields in the schema and generates appropriate protobuf types.
289
+ *
290
+ * @param schema - Zod schema to traverse
291
+ * @param messages - Map of message names to their protobuf fields
292
+ * @param enums - Map of enum names to their protobuf values
293
+ * @param typePrefix - Optional prefix for type names
294
+ * @param parentKey - Optional parent message name for nested types
295
+ * @returns Array of protobuf field definition strings
296
+ */
206
297
  const traverseSchema = ({ schema, messages, enums, typePrefix, parentKey }) => {
207
298
  if (!schema || typeof schema !== "object" || !("def" in schema) || schema.constructor.name !== "ZodObject" && schema.def.type !== "object") return [];
208
299
  const zodObject = schema;
@@ -222,6 +313,14 @@ const traverseSchema = ({ schema, messages, enums, typePrefix, parentKey }) => {
222
313
 
223
314
  //#endregion
224
315
  //#region src/service-generator.ts
316
+ /**
317
+ * Parses a Zod service schema and extracts method definitions.
318
+ * Each method must be a function with one argument (request) and a return value (response).
319
+ *
320
+ * @param name - Service name
321
+ * @param schema - Zod object containing service methods as functions
322
+ * @returns Service definition with extracted methods
323
+ */
225
324
  const parseZodServiceSchema = (name, schema) => {
226
325
  const shape = schema.shape;
227
326
  const methods = [];
@@ -246,22 +345,60 @@ const parseZodServiceSchema = (name, schema) => {
246
345
  methods
247
346
  };
248
347
  };
348
+ /**
349
+ * Normalizes service input data into an array of service definitions.
350
+ * If an array is passed, returns it as is.
351
+ * If an object is passed, converts each key-value pair into a service definition.
352
+ *
353
+ * @param services - Array of service definitions or object with Zod schemas
354
+ * @returns Array of normalized service definitions
355
+ */
249
356
  const normalizeServices = (services) => {
250
357
  if (Array.isArray(services)) return services;
251
358
  return Object.entries(services).map(([name, schema]) => parseZodServiceSchema(name, schema));
252
359
  };
360
+ /**
361
+ * Ensures that the schema is a ZodObject.
362
+ * If the schema is already an object, returns it as is.
363
+ * Otherwise, wraps the schema in an object with a "data" field.
364
+ *
365
+ * @param schema - Zod schema of any type
366
+ * @returns ZodObject containing the original schema
367
+ */
253
368
  const ensureZodObject = (schema) => {
254
369
  if ((schema.def.type || schema.constructor.name) === "object" || schema.constructor.name === "ZodObject") return schema;
255
370
  return z.object({ data: schema });
256
371
  };
372
+ /**
373
+ * Generates the name for a request message based on the method name.
374
+ *
375
+ * @param methodName - Name of the service method
376
+ * @param typePrefix - Optional prefix for type names
377
+ * @returns Generated request message name in PascalCase
378
+ */
257
379
  const generateRequestMessageName = (methodName, typePrefix) => {
258
380
  const messageName = toPascalCase({ value: `${methodName}Request` });
259
381
  return typePrefix ? `${typePrefix}${messageName}` : messageName;
260
382
  };
383
+ /**
384
+ * Generates the name for a response message based on the method name.
385
+ *
386
+ * @param methodName - Name of the service method
387
+ * @param typePrefix - Optional prefix for type names
388
+ * @returns Generated response message name in PascalCase
389
+ */
261
390
  const generateResponseMessageName = (methodName, typePrefix) => {
262
391
  const messageName = toPascalCase({ value: `${methodName}Response` });
263
392
  return typePrefix ? `${typePrefix}${messageName}` : messageName;
264
393
  };
394
+ /**
395
+ * Processes a service method by generating request and response message names
396
+ * and traversing their schemas to populate the context with message definitions.
397
+ *
398
+ * @param method - Service method definition
399
+ * @param context - Generation context containing messages, enums, and type prefix
400
+ * @returns Object containing request and response message names
401
+ */
265
402
  const processServiceMethod = (method, context) => {
266
403
  const { messages, enums, typePrefix } = context;
267
404
  const requestName = generateRequestMessageName(method.name, typePrefix);
@@ -291,6 +428,14 @@ const processServiceMethod = (method, context) => {
291
428
  responseName
292
429
  };
293
430
  };
431
+ /**
432
+ * Generates protobuf service definitions from Zod service schemas.
433
+ * Supports streaming methods (client, server, bidirectional).
434
+ *
435
+ * @param services - Service definitions as array or object with Zod schemas
436
+ * @param context - Generation context containing messages, enums, and type prefix
437
+ * @returns Array of protobuf service definition strings
438
+ */
294
439
  const generateServices = (services, context) => {
295
440
  return normalizeServices(services).map((service) => {
296
441
  const methods = service.methods.map((method) => {
@@ -307,9 +452,24 @@ const generateServices = (services, context) => {
307
452
 
308
453
  //#endregion
309
454
  //#region src/zod-to-protobuf.ts
455
+ /**
456
+ * Generates a protobuf definition string for services only (without root message).
457
+ * Convenience function that calls zodToProtobuf with an empty schema.
458
+ *
459
+ * @param options - Options for protobuf generation
460
+ * @returns Protobuf definition string
461
+ */
310
462
  const zodToProtobufService = (options = {}) => {
311
463
  return zodToProtobuf(z.object(), options);
312
464
  };
465
+ /**
466
+ * Converts a Zod schema to a protobuf definition string.
467
+ * Generates messages, enums, and services based on the provided schema and options.
468
+ *
469
+ * @param schema - Optional Zod schema to convert (if not provided, only services will be generated)
470
+ * @param options - Options for protobuf generation including package name, root message name, type prefix, and services
471
+ * @returns Complete protobuf definition string
472
+ */
313
473
  const zodToProtobuf = (schema, options = {}) => {
314
474
  const { packageName = "default", rootMessageName = "Message", typePrefix = "", services, skipRootMessage = false } = options;
315
475
  const messages = /* @__PURE__ */ new Map();
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["tupleFields: ProtobufField[]","methods: ServiceMethod[]"],"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\nexport const getNumberTypeName = ({ value }: { value: ZodNumber }): string => {\n return value.isInt ? \"int32\" : \"double\";\n};\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\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\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\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\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\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 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\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\ninterface ServiceGenerationContext {\n messages: Map<string, string[]>;\n enums: Map<string, string[]>;\n typePrefix: string | null;\n}\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 methods.push({\n name: methodName,\n request,\n response,\n });\n }\n }\n }\n\n return {\n name,\n methods,\n };\n};\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\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\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\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\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\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\nexport const zodToProtobufService = (\n options: ZodToProtobufOptions = {}\n): string => {\n return zodToProtobuf(z.object(), options);\n};\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 const 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[]"],"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 methods.push({\n name: methodName,\n request,\n response,\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 const 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,6 +1,6 @@
1
1
  {
2
2
  "name": "@globalart/zod-to-proto",
3
- "version": "1.0.14",
3
+ "version": "1.0.15",
4
4
  "author": {
5
5
  "name": "GlobalArt, Inc"
6
6
  },
@@ -56,7 +56,7 @@
56
56
  "prettier": "^3.6.2",
57
57
  "release-it": "19.0.6",
58
58
  "ts-node": "^10.9.2",
59
- "tsdown": "0.16.4",
59
+ "tsdown": "0.16.5",
60
60
  "typescript": "^5.9.3"
61
61
  },
62
62
  "dependencies": {