@globalart/zod-to-proto 1.0.5 → 1.0.7

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/README.md CHANGED
@@ -56,6 +56,52 @@ message Message {
56
56
 
57
57
  ### Generating gRPC Services
58
58
 
59
+ There are two ways to define gRPC services:
60
+
61
+ #### Option 1: Using Zod Schemas with Functions (Recommended)
62
+
63
+ ```typescript
64
+ import { zodToProtobuf } from "@globalart/zod-to-proto";
65
+ import { z } from "zod";
66
+
67
+ // Define request/response schemas
68
+ const getUserByIdRequestSchema = z.object({
69
+ id: z.number().int(),
70
+ });
71
+
72
+ const userSchema = z.object({
73
+ id: z.number().int(),
74
+ name: z.string(),
75
+ email: z.string(),
76
+ });
77
+
78
+ // Define service using z.function()
79
+ const userServiceSchema = z.object({
80
+ getUserById: z.function({
81
+ input: [getUserByIdRequestSchema],
82
+ output: userSchema,
83
+ }),
84
+ createUser: z.function({
85
+ input: [userSchema],
86
+ output: z.object({
87
+ id: z.number().int(),
88
+ success: z.boolean(),
89
+ }),
90
+ }),
91
+ });
92
+
93
+ const protoDefinition = zodToProtobuf(z.object(), {
94
+ packageName: "user.service",
95
+ services: {
96
+ UserService: userServiceSchema,
97
+ },
98
+ });
99
+
100
+ console.log(protoDefinition);
101
+ ```
102
+
103
+ #### Option 2: Using Service Definitions Array
104
+
59
105
  ```typescript
60
106
  import { zodToProtobuf } from "@globalart/zod-to-proto";
61
107
  import { z } from "zod";
@@ -97,36 +143,36 @@ const protoDefinition = zodToProtobuf(z.object(), {
97
143
  console.log(protoDefinition);
98
144
  ```
99
145
 
100
- Output:
146
+ Both approaches produce the same output:
101
147
 
102
148
  ```protobuf
103
149
  syntax = "proto3";
104
150
  package user.service;
105
151
 
106
- message GetUserRequest {
107
- string id = 1;
152
+ message GetUserByIdRequest {
153
+ int32 id = 1;
108
154
  }
109
155
 
110
- message GetUserResponse {
111
- string name = 1;
112
- int32 age = 2;
156
+ message GetUserByIdResponse {
157
+ int32 id = 1;
158
+ string name = 2;
113
159
  string email = 3;
114
160
  }
115
161
 
116
162
  message CreateUserRequest {
117
- string name = 1;
118
- int32 age = 2;
163
+ int32 id = 1;
164
+ string name = 2;
119
165
  string email = 3;
120
166
  }
121
167
 
122
168
  message CreateUserResponse {
123
- string id = 1;
169
+ int32 id = 1;
124
170
  bool success = 2;
125
171
  }
126
172
 
127
173
  service UserService {
128
- rpc getUser(GetUserRequest) returns (GetUserResponse);
129
- rpc createUser(CreateUserRequest) returns (CreateUserResponse);
174
+ rpc GetUserById(GetUserByIdRequest) returns (GetUserByIdResponse);
175
+ rpc CreateUser(CreateUserRequest) returns (CreateUserResponse);
130
176
  }
131
177
  ```
132
178
 
@@ -145,16 +191,41 @@ Converts a Zod schema to a Protobuf definition.
145
191
 
146
192
  ```typescript
147
193
  interface ZodToProtobufOptions {
148
- packageName?: string; // Protobuf package name (default: "default")
149
- rootMessageName?: string; // Root message name (default: "Message")
150
- typePrefix?: string; // Prefix for message and enum types
151
- services?: ServiceDefinition[]; // gRPC service definitions
152
- skipRootMessage?: boolean; // Skip root message generation
194
+ packageName?: string; // Protobuf package name (default: "default")
195
+ rootMessageName?: string; // Root message name (default: "Message")
196
+ typePrefix?: string; // Prefix for message and enum types
197
+ services?: ServicesInput; // gRPC service definitions
198
+ skipRootMessage?: boolean; // Skip root message generation
153
199
  }
200
+
201
+ type ServicesInput = ServiceDefinition[] | Record<string, ZodObject<any>>;
154
202
  ```
155
203
 
156
204
  #### Service Definition
157
205
 
206
+ You can define services in two ways:
207
+
208
+ **Option 1: Using Zod Schemas (Recommended)**
209
+
210
+ ```typescript
211
+ const serviceSchema = z.object({
212
+ methodName: z.function({
213
+ input: [requestSchema],
214
+ output: responseSchema,
215
+ }),
216
+ // ... more methods
217
+ });
218
+
219
+ // Use in options
220
+ const proto = zodToProtobuf(z.object(), {
221
+ services: {
222
+ ServiceName: serviceSchema,
223
+ },
224
+ });
225
+ ```
226
+
227
+ **Option 2: Using Service Definitions Array**
228
+
158
229
  ```typescript
159
230
  interface ServiceDefinition {
160
231
  name: string; // Service name
@@ -183,7 +254,7 @@ interface ServiceMethod {
183
254
 
184
255
  - `z.array()` → `repeated`
185
256
  - `z.set()` → `repeated`
186
- - `z.map()` → `map<keyType, valueType>`
257
+ - `z.map()` → `map<keyType, valueType>` (key must be int32, int64, string, or bool)
187
258
  - `z.tuple()` → nested message
188
259
 
189
260
  ### Complex Types
@@ -282,12 +353,113 @@ const protoDefinition = zodToProtobuf(schema, {
282
353
  });
283
354
  ```
284
355
 
356
+ ## Advanced Usage
357
+
358
+ ### Working with Maps
359
+
360
+ Protobuf maps have strict key type requirements. Only integral types, strings, and booleans are allowed as keys:
361
+
362
+ ```typescript
363
+ const schema = z.object({
364
+ // ✅ Valid map keys
365
+ usersByStringId: z.map(z.string(), userSchema),
366
+ usersByIntId: z.map(z.number().int(), userSchema),
367
+ flagsMap: z.map(z.boolean(), z.string()),
368
+
369
+ // ❌ Invalid - double is not allowed as map key
370
+ invalidMap: z.map(z.number(), userSchema), // Use .int() instead!
371
+ });
372
+ ```
373
+
374
+ ### Type-Safe Service Definitions
375
+
376
+ When using Zod schemas for services, you get full TypeScript type safety:
377
+
378
+ ```typescript
379
+ const userServiceSchema = z.object({
380
+ getUser: z.function({
381
+ input: [z.object({ id: z.number().int() })],
382
+ output: userSchema,
383
+ }),
384
+ });
385
+
386
+ type UserService = z.infer<typeof userServiceSchema>;
387
+
388
+ // Implementation with type checking
389
+ class UserServiceImpl implements UserService {
390
+ async getUser({ id }: { id: number }) {
391
+ // TypeScript knows the shape of input and output
392
+ return { id, name: "John", email: "john@example.com" };
393
+ }
394
+ }
395
+ ```
396
+
397
+ ### Avoiding Circular Dependencies
398
+
399
+ **Important:** Avoid circular dependencies between schema files. Circular imports will cause types to become `undefined` during schema construction.
400
+
401
+ ❌ **Bad Example:**
402
+ ```typescript
403
+ // user.schema.ts
404
+ import { getUserByIdResponseSchema } from "./get-user-by-id.schema";
405
+
406
+ export const userSchema = z.object({ ... });
407
+
408
+ export const userServiceSchema = z.object({
409
+ getUserById: z.function({
410
+ input: [...],
411
+ output: getUserByIdResponseSchema, // ❌ Circular dependency
412
+ }),
413
+ });
414
+
415
+ // get-user-by-id.schema.ts
416
+ import { userSchema } from "./user.schema"; // ❌ Circular dependency
417
+
418
+ export const getUserByIdResponseSchema = userSchema;
419
+ ```
420
+
421
+ ✅ **Good Example:**
422
+ ```typescript
423
+ // user.schema.ts
424
+ import { getUserByIdRequestSchema } from "./get-user-by-id.schema";
425
+
426
+ export const userSchema = z.object({ ... });
427
+
428
+ export const userServiceSchema = z.object({
429
+ getUserById: z.function({
430
+ input: [getUserByIdRequestSchema],
431
+ output: userSchema, // ✅ Direct reference, no circular dependency
432
+ }),
433
+ });
434
+
435
+ // get-user-by-id.schema.ts
436
+ export const getUserByIdRequestSchema = z.object({ id: z.number().int() });
437
+ // No import of userSchema needed
438
+ ```
439
+
440
+ ### Multiple Services
441
+
442
+ You can define multiple services in a single protobuf file:
443
+
444
+ ```typescript
445
+ const protoDefinition = zodToProtobuf(z.object(), {
446
+ packageName: "api.v1",
447
+ services: {
448
+ UserService: userServiceSchema,
449
+ AuthService: authServiceSchema,
450
+ ProductService: productServiceSchema,
451
+ },
452
+ });
453
+ ```
454
+
285
455
  ## Limitations
286
456
 
287
457
  - Only the types listed above are supported
288
458
  - Unsupported types will throw `UnsupportedTypeException`
289
459
  - Nested objects are automatically converted to separate messages
290
460
  - Enum values are converted to numbers starting from 0
461
+ - Map keys must be integral types (int32, int64, etc.), strings, or booleans - **not** doubles or floats
462
+ - Avoid circular dependencies between schema files
291
463
 
292
464
  ## License
293
465
 
package/dist/index.cjs CHANGED
@@ -65,9 +65,10 @@ const traverseArray = ({ key, value, messages, enums, typePrefix }) => {
65
65
  }));
66
66
  };
67
67
  const traverseMap = ({ key, value, messages, enums, typePrefix }) => {
68
+ const mapDef = value._def || value.def;
68
69
  const keyType = traverseKey({
69
- key: `${key}Key`,
70
- value: value._def.keyType,
70
+ key: inflection.singularize(key),
71
+ value: mapDef.keyType || value.keyType,
71
72
  messages,
72
73
  enums,
73
74
  isOptional: false,
@@ -75,8 +76,8 @@ const traverseMap = ({ key, value, messages, enums, typePrefix }) => {
75
76
  typePrefix
76
77
  });
77
78
  const valueType = traverseKey({
78
- key: `${key}Value`,
79
- value: value._def.valueType,
79
+ key: inflection.singularize(key),
80
+ value: mapDef.valueType || value.valueType,
80
81
  messages,
81
82
  enums,
82
83
  isOptional: false,
@@ -91,6 +92,7 @@ const traverseMap = ({ key, value, messages, enums, typePrefix }) => {
91
92
  }];
92
93
  };
93
94
  const traverseKey = ({ key, value, messages, enums, isOptional, isInArray, typePrefix }) => {
95
+ if (!value) return [];
94
96
  if (value instanceof zod.ZodOptional || value instanceof zod.ZodNullable) return traverseKey({
95
97
  key,
96
98
  value: value.unwrap(),
@@ -183,8 +185,9 @@ const traverseKey = ({ key, value, messages, enums, isOptional, isInArray, typeP
183
185
  throw new UnsupportedTypeException(typeof value);
184
186
  };
185
187
  const traverseSchema = ({ schema, messages, enums, typePrefix }) => {
186
- if (!(schema instanceof zod.ZodObject)) throw new UnsupportedTypeException(schema.constructor.name);
187
- return Object.entries(schema.shape).flatMap(([key, value]) => {
188
+ if (!schema || typeof schema !== "object" || !("_def" in schema) || schema.constructor.name !== "ZodObject" && schema._def.type !== "object") throw new UnsupportedTypeException(schema?.constructor?.name || typeof schema);
189
+ const zodObject = schema;
190
+ return Object.entries(zodObject.shape).flatMap(([key, value]) => {
188
191
  return traverseKey({
189
192
  key,
190
193
  value,
@@ -199,6 +202,38 @@ const traverseSchema = ({ schema, messages, enums, typePrefix }) => {
199
202
 
200
203
  //#endregion
201
204
  //#region src/service-generator.ts
205
+ const parseZodServiceSchema = (name, schema) => {
206
+ const shape = schema.shape;
207
+ const methods = [];
208
+ for (const [methodName, methodSchema] of Object.entries(shape)) {
209
+ const methodDef = methodSchema._def;
210
+ if (methodDef.type === "function") {
211
+ const args = methodDef.input?.def?.items ?? [];
212
+ const output = methodDef.output;
213
+ if (args.length > 0 && args[0] && output) {
214
+ const request = args[0];
215
+ const response = output;
216
+ methods.push({
217
+ name: methodName,
218
+ request,
219
+ response
220
+ });
221
+ }
222
+ }
223
+ }
224
+ return {
225
+ name,
226
+ methods
227
+ };
228
+ };
229
+ const normalizeServices = (services) => {
230
+ if (Array.isArray(services)) return services;
231
+ return Object.entries(services).map(([name, schema]) => parseZodServiceSchema(name, schema));
232
+ };
233
+ const ensureZodObject = (schema) => {
234
+ if ((schema._def.type || schema.constructor.name) === "object" || schema.constructor.name === "ZodObject") return schema;
235
+ return zod.z.object({ data: schema });
236
+ };
202
237
  const generateRequestMessageName = (methodName, typePrefix) => {
203
238
  const messageName = toPascalCase({ value: `${methodName}Request` });
204
239
  return typePrefix ? `${typePrefix}${messageName}` : messageName;
@@ -213,7 +248,7 @@ const processServiceMethod = (method, context) => {
213
248
  const responseName = generateResponseMessageName(method.name, typePrefix);
214
249
  if (!messages.has(requestName)) {
215
250
  const requestFields = traverseSchema({
216
- schema: method.request,
251
+ schema: ensureZodObject(method.request),
217
252
  messages,
218
253
  enums,
219
254
  typePrefix
@@ -222,7 +257,7 @@ const processServiceMethod = (method, context) => {
222
257
  }
223
258
  if (!messages.has(responseName)) {
224
259
  const responseFields = traverseSchema({
225
- schema: method.response,
260
+ schema: ensureZodObject(method.response),
226
261
  messages,
227
262
  enums,
228
263
  typePrefix
@@ -235,7 +270,7 @@ const processServiceMethod = (method, context) => {
235
270
  };
236
271
  };
237
272
  const generateServices = (services, context) => {
238
- return services.map((service) => {
273
+ return normalizeServices(services).map((service) => {
239
274
  const methods = service.methods.map((method) => {
240
275
  const { requestName, responseName } = processServiceMethod(method, context);
241
276
  const requestStreaming = method.streaming === "client" || method.streaming === "bidirectional";
@@ -251,7 +286,7 @@ const generateServices = (services, context) => {
251
286
  //#endregion
252
287
  //#region src/zod-to-protobuf.ts
253
288
  const zodToProtobuf = (schema, options = {}) => {
254
- const { packageName = "default", rootMessageName = "Message", typePrefix = "", services = [], skipRootMessage = false } = options;
289
+ const { packageName = "default", rootMessageName = "Message", typePrefix = "", services, skipRootMessage = false } = options;
255
290
  const messages = /* @__PURE__ */ new Map();
256
291
  const enums = /* @__PURE__ */ new Map();
257
292
  if (schema && !skipRootMessage) {
@@ -271,7 +306,7 @@ const zodToProtobuf = (schema, options = {}) => {
271
306
  enums,
272
307
  typePrefix: typePrefix || null
273
308
  };
274
- if (services.length > 0) generateServices(services, context);
309
+ const servicesString = services && (Array.isArray(services) ? services.length > 0 : Object.keys(services).length > 0) ? generateServices(services, context) : [];
275
310
  return `
276
311
  syntax = "proto3";
277
312
  package ${packageName};
@@ -279,7 +314,7 @@ package ${packageName};
279
314
  ${[
280
315
  Array.from(enums.values()).map((enumDef) => enumDef.join("\n")),
281
316
  Array.from(messages.entries()).map(([name, fields]) => `message ${name} {\n${fields.map((field) => ` ${field}`).join("\n")}\n}`),
282
- services.length > 0 ? generateServices(services, context) : []
317
+ servicesString
283
318
  ].filter((strings) => !!strings.length).map((strings) => strings.join("\n\n")).join("\n\n")}
284
319
  `.trim();
285
320
  };
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["ZodArray","ZodSet","ZodOptional","ZodNullable","ZodMap","ZodObject","ZodString","ZodNumber","ZodBoolean","ZodEnum","ZodDate","ZodBigInt","ZodTuple","tupleFields: ProtobufField[]","ZodType"],"sources":["../src/types.ts","../src/utils.ts","../src/traversers.ts","../src/service-generator.ts","../src/zod-to-protobuf.ts"],"sourcesContent":["import type { ZodTypeAny } from \"zod\";\n\nexport interface ZodToProtobufOptions {\n packageName?: string;\n rootMessageName?: string;\n typePrefix?: string;\n services?: ServiceDefinition[];\n skipRootMessage?: boolean;\n}\n\nexport interface ServiceMethod {\n name: string;\n request: ZodTypeAny;\n response: ZodTypeAny;\n streaming?: \"client\" | \"server\" | \"bidirectional\";\n}\n\nexport interface ServiceDefinition {\n name: string;\n methods: ServiceMethod[];\n}\n\nexport class UnsupportedTypeException extends Error {\n constructor(type: string) {\n super(`Unsupported type: ${type}`);\n this.name = \"UnsupportedTypeException\";\n }\n}\n\nexport interface ProtobufField {\n types: Array<string | null>;\n name: string;\n}\n","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 ZodSet,\n ZodString,\n ZodTuple,\n ZodType,\n type ZodTypeAny,\n} from \"zod\";\nimport { UnsupportedTypeException, type ProtobufField } from \"./types\";\nimport { getNumberTypeName, toPascalCase, protobufFieldToType } from \"./utils\";\n\nexport const traverseArray = ({\n key,\n value,\n messages,\n enums,\n typePrefix,\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}): ProtobufField[] => {\n const nestedValue =\n value instanceof ZodArray\n ? value.element\n : value instanceof ZodSet\n ? (value._def as { valueType: ZodTypeAny }).valueType\n : // @ts-expect-error\n (value._def as { element?: ZodTypeAny }).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 });\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}: {\n key: string;\n value: ZodMap<ZodTypeAny, ZodTypeAny>;\n messages: Map<string, string[]>;\n enums: Map<string, string[]>;\n typePrefix: string | null;\n}): ProtobufField[] => {\n const keyType = traverseKey({\n key: `${key}Key`,\n value: value._def.keyType,\n messages,\n enums,\n isOptional: false,\n isInArray: true,\n typePrefix,\n });\n const valueType = traverseKey({\n key: `${key}Value`,\n value: value._def.valueType,\n messages,\n enums,\n isOptional: false,\n isInArray: true,\n typePrefix,\n });\n\n if (!keyType[0] || keyType.length !== 1) {\n throw new UnsupportedTypeException(`${key} map key`);\n }\n\n if (!valueType[0] || valueType.length !== 1) {\n throw new UnsupportedTypeException(`${key} map value`);\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}: {\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}): ProtobufField[] => {\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 });\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 });\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 });\n }\n\n const optional = isOptional && !isInArray ? \"optional\" : null;\n\n if (value instanceof ZodObject) {\n let messageName = toPascalCase({ value: key });\n if (typePrefix) {\n messageName = `${typePrefix}${messageName}`;\n }\n const nestedMessageFields = traverseSchema({\n schema: value,\n messages,\n enums,\n typePrefix,\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 (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 });\n });\n\n const tupleMessageName = toPascalCase({ value: key });\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 throw new UnsupportedTypeException(value.constructor.name);\n }\n\n throw new UnsupportedTypeException(typeof value);\n};\n\nexport const traverseSchema = ({\n schema,\n messages,\n enums,\n typePrefix,\n}: {\n schema: ZodTypeAny;\n messages: Map<string, string[]>;\n enums: Map<string, string[]>;\n typePrefix: string | null;\n}): string[] => {\n if (!(schema instanceof ZodObject)) {\n throw new UnsupportedTypeException(schema.constructor.name);\n }\n\n const fields = Object.entries(schema.shape).flatMap(([key, value]) => {\n return traverseKey({\n key,\n value,\n messages,\n enums,\n isOptional: false,\n isInArray: false,\n typePrefix,\n });\n });\n\n return fields.map(\n (field, index) =>\n `${protobufFieldToType({ field })} ${field.name} = ${index + 1};`,\n );\n};\n","import type { ZodTypeAny } from \"zod\";\nimport type { ServiceDefinition, ServiceMethod } 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 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 requestFields = traverseSchema({\n schema: method.request,\n messages,\n enums,\n typePrefix,\n });\n messages.set(requestName, requestFields);\n }\n\n if (!messages.has(responseName)) {\n const responseFields = traverseSchema({\n schema: method.response,\n messages,\n enums,\n typePrefix,\n });\n messages.set(responseName, responseFields);\n }\n\n return { requestName, responseName };\n};\n\nexport const generateServices = (\n services: ServiceDefinition[],\n context: ServiceGenerationContext\n): string[] => {\n return services.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\";\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 if (services.length > 0) {\n generateServices(services, context);\n }\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 servicesString =\n services.length > 0 ? generateServices(services, context) : [];\n\n const content = [enumsString, messagesString, servicesString]\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","ZodOptional","ZodNullable","ZodMap","ZodObject","ZodString","ZodNumber","ZodBoolean","ZodEnum","ZodDate","ZodBigInt","ZodTuple","tupleFields: ProtobufField[]","ZodType","methods: ServiceMethod[]","z"],"sources":["../src/types.ts","../src/utils.ts","../src/traversers.ts","../src/service-generator.ts","../src/zod-to-protobuf.ts"],"sourcesContent":["import type { ZodObject, ZodTypeAny } from \"zod\";\n\nexport type ServicesInput =\n | ServiceDefinition[]\n | Record<string, ZodObject<any>>;\n\nexport interface ZodToProtobufOptions {\n packageName?: string;\n rootMessageName?: string;\n typePrefix?: string;\n services?: ServicesInput;\n skipRootMessage?: boolean;\n}\n\nexport interface ServiceMethod {\n name: string;\n request: ZodTypeAny;\n response: ZodTypeAny;\n streaming?: \"client\" | \"server\" | \"bidirectional\";\n}\n\nexport interface ServiceDefinition {\n name: string;\n methods: ServiceMethod[];\n}\n\nexport class UnsupportedTypeException extends Error {\n constructor(type: string) {\n super(`Unsupported type: ${type}`);\n this.name = \"UnsupportedTypeException\";\n }\n}\n\nexport interface ProtobufField {\n types: Array<string | null>;\n name: string;\n}\n","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 ZodSet,\n ZodString,\n ZodTuple,\n ZodType,\n type ZodTypeAny,\n} from \"zod\";\nimport { UnsupportedTypeException, type ProtobufField } from \"./types\";\nimport { getNumberTypeName, toPascalCase, protobufFieldToType } from \"./utils\";\n\nexport const traverseArray = ({\n key,\n value,\n messages,\n enums,\n typePrefix,\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}): ProtobufField[] => {\n const nestedValue =\n value instanceof ZodArray\n ? value.element\n : value instanceof ZodSet\n ? (value._def as { valueType: ZodTypeAny }).valueType\n : // @ts-expect-error\n (value._def as { element?: ZodTypeAny }).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 });\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}: {\n key: string;\n value: ZodMap<ZodTypeAny, ZodTypeAny>;\n messages: Map<string, string[]>;\n enums: Map<string, string[]>;\n typePrefix: string | null;\n}): ProtobufField[] => {\n const mapDef = (value._def || value.def) as {\n keyType?: ZodTypeAny;\n valueType?: ZodTypeAny;\n };\n\n const keyType = traverseKey({\n key: inflection.singularize(key),\n value:\n mapDef.keyType ||\n (value as ZodTypeAny & { keyType?: ZodTypeAny }).keyType,\n messages,\n enums,\n isOptional: false,\n isInArray: true,\n typePrefix,\n });\n const valueType = traverseKey({\n key: inflection.singularize(key),\n value:\n mapDef.valueType ||\n (value as ZodTypeAny & { valueType?: ZodTypeAny }).valueType,\n messages,\n enums,\n isOptional: false,\n isInArray: true,\n typePrefix,\n });\n\n if (!keyType[0] || keyType.length !== 1) {\n throw new UnsupportedTypeException(`${key} map key`);\n }\n\n if (!valueType[0] || valueType.length !== 1) {\n throw new UnsupportedTypeException(`${key} map value`);\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}: {\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}): 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 });\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 });\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 });\n }\n\n const optional = isOptional && !isInArray ? \"optional\" : null;\n\n if (value instanceof ZodObject) {\n let messageName = toPascalCase({ value: key });\n if (typePrefix) {\n messageName = `${typePrefix}${messageName}`;\n }\n const nestedMessageFields = traverseSchema({\n schema: value,\n messages,\n enums,\n typePrefix,\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 (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 });\n });\n\n const tupleMessageName = toPascalCase({ value: key });\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 throw new UnsupportedTypeException(value.constructor.name);\n }\n\n throw new UnsupportedTypeException(typeof value);\n};\n\nexport const traverseSchema = ({\n schema,\n messages,\n enums,\n typePrefix,\n}: {\n schema: ZodTypeAny;\n messages: Map<string, string[]>;\n enums: Map<string, string[]>;\n typePrefix: string | null;\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 throw new UnsupportedTypeException(\n schema?.constructor?.name || typeof schema\n );\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 });\n });\n\n return fields.map(\n (field, index) =>\n `${protobufFieldToType({ field })} ${field.name} = ${index + 1};`\n );\n};\n","import { z, type ZodFunction, ZodObject, type ZodTypeAny } from \"zod\";\nimport type { ServiceDefinition, ServiceMethod, ServicesInput } 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 {\n type?: string;\n input?: ZodTypeAny;\n output?: ZodTypeAny;\n };\n\n if (methodDef.type === \"function\") {\n const inputDef = methodDef.input as ZodTypeAny & {\n def?: { items?: ZodTypeAny[] };\n };\n\n const args = inputDef?.def?.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 });\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 });\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\";\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 = [enumsString, messagesString, servicesString]\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/dist/index.d.cts CHANGED
@@ -1,11 +1,12 @@
1
- import { ZodTypeAny } from "zod";
1
+ import { ZodObject, ZodTypeAny } from "zod";
2
2
 
3
3
  //#region src/types.d.ts
4
+ type ServicesInput = ServiceDefinition[] | Record<string, ZodObject<any>>;
4
5
  interface ZodToProtobufOptions {
5
6
  packageName?: string;
6
7
  rootMessageName?: string;
7
8
  typePrefix?: string;
8
- services?: ServiceDefinition[];
9
+ services?: ServicesInput;
9
10
  skipRootMessage?: boolean;
10
11
  }
11
12
  interface ServiceMethod {
package/dist/index.d.mts CHANGED
@@ -1,11 +1,12 @@
1
- import { ZodTypeAny } from "zod";
1
+ import { ZodObject, ZodTypeAny } from "zod";
2
2
 
3
3
  //#region src/types.d.ts
4
+ type ServicesInput = ServiceDefinition[] | Record<string, ZodObject<any>>;
4
5
  interface ZodToProtobufOptions {
5
6
  packageName?: string;
6
7
  rootMessageName?: string;
7
8
  typePrefix?: string;
8
- services?: ServiceDefinition[];
9
+ services?: ServicesInput;
9
10
  skipRootMessage?: boolean;
10
11
  }
11
12
  interface ServiceMethod {
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as inflection from "inflection";
2
- import { ZodArray, ZodBigInt, ZodBoolean, ZodDate, ZodEnum, ZodMap, ZodNullable, ZodNumber, ZodObject, ZodOptional, ZodSet, ZodString, ZodTuple, ZodType } from "zod";
2
+ import { ZodArray, ZodBigInt, ZodBoolean, ZodDate, ZodEnum, ZodMap, ZodNullable, ZodNumber, ZodObject, ZodOptional, ZodSet, ZodString, ZodTuple, ZodType, z } from "zod";
3
3
 
4
4
  //#region src/types.ts
5
5
  var UnsupportedTypeException = class extends Error {
@@ -41,9 +41,10 @@ const traverseArray = ({ key, value, messages, enums, typePrefix }) => {
41
41
  }));
42
42
  };
43
43
  const traverseMap = ({ key, value, messages, enums, typePrefix }) => {
44
+ const mapDef = value._def || value.def;
44
45
  const keyType = traverseKey({
45
- key: `${key}Key`,
46
- value: value._def.keyType,
46
+ key: inflection.singularize(key),
47
+ value: mapDef.keyType || value.keyType,
47
48
  messages,
48
49
  enums,
49
50
  isOptional: false,
@@ -51,8 +52,8 @@ const traverseMap = ({ key, value, messages, enums, typePrefix }) => {
51
52
  typePrefix
52
53
  });
53
54
  const valueType = traverseKey({
54
- key: `${key}Value`,
55
- value: value._def.valueType,
55
+ key: inflection.singularize(key),
56
+ value: mapDef.valueType || value.valueType,
56
57
  messages,
57
58
  enums,
58
59
  isOptional: false,
@@ -67,6 +68,7 @@ const traverseMap = ({ key, value, messages, enums, typePrefix }) => {
67
68
  }];
68
69
  };
69
70
  const traverseKey = ({ key, value, messages, enums, isOptional, isInArray, typePrefix }) => {
71
+ if (!value) return [];
70
72
  if (value instanceof ZodOptional || value instanceof ZodNullable) return traverseKey({
71
73
  key,
72
74
  value: value.unwrap(),
@@ -159,8 +161,9 @@ const traverseKey = ({ key, value, messages, enums, isOptional, isInArray, typeP
159
161
  throw new UnsupportedTypeException(typeof value);
160
162
  };
161
163
  const traverseSchema = ({ schema, messages, enums, typePrefix }) => {
162
- if (!(schema instanceof ZodObject)) throw new UnsupportedTypeException(schema.constructor.name);
163
- return Object.entries(schema.shape).flatMap(([key, value]) => {
164
+ if (!schema || typeof schema !== "object" || !("_def" in schema) || schema.constructor.name !== "ZodObject" && schema._def.type !== "object") throw new UnsupportedTypeException(schema?.constructor?.name || typeof schema);
165
+ const zodObject = schema;
166
+ return Object.entries(zodObject.shape).flatMap(([key, value]) => {
164
167
  return traverseKey({
165
168
  key,
166
169
  value,
@@ -175,6 +178,38 @@ const traverseSchema = ({ schema, messages, enums, typePrefix }) => {
175
178
 
176
179
  //#endregion
177
180
  //#region src/service-generator.ts
181
+ const parseZodServiceSchema = (name, schema) => {
182
+ const shape = schema.shape;
183
+ const methods = [];
184
+ for (const [methodName, methodSchema] of Object.entries(shape)) {
185
+ const methodDef = methodSchema._def;
186
+ if (methodDef.type === "function") {
187
+ const args = methodDef.input?.def?.items ?? [];
188
+ const output = methodDef.output;
189
+ if (args.length > 0 && args[0] && output) {
190
+ const request = args[0];
191
+ const response = output;
192
+ methods.push({
193
+ name: methodName,
194
+ request,
195
+ response
196
+ });
197
+ }
198
+ }
199
+ }
200
+ return {
201
+ name,
202
+ methods
203
+ };
204
+ };
205
+ const normalizeServices = (services) => {
206
+ if (Array.isArray(services)) return services;
207
+ return Object.entries(services).map(([name, schema]) => parseZodServiceSchema(name, schema));
208
+ };
209
+ const ensureZodObject = (schema) => {
210
+ if ((schema._def.type || schema.constructor.name) === "object" || schema.constructor.name === "ZodObject") return schema;
211
+ return z.object({ data: schema });
212
+ };
178
213
  const generateRequestMessageName = (methodName, typePrefix) => {
179
214
  const messageName = toPascalCase({ value: `${methodName}Request` });
180
215
  return typePrefix ? `${typePrefix}${messageName}` : messageName;
@@ -189,7 +224,7 @@ const processServiceMethod = (method, context) => {
189
224
  const responseName = generateResponseMessageName(method.name, typePrefix);
190
225
  if (!messages.has(requestName)) {
191
226
  const requestFields = traverseSchema({
192
- schema: method.request,
227
+ schema: ensureZodObject(method.request),
193
228
  messages,
194
229
  enums,
195
230
  typePrefix
@@ -198,7 +233,7 @@ const processServiceMethod = (method, context) => {
198
233
  }
199
234
  if (!messages.has(responseName)) {
200
235
  const responseFields = traverseSchema({
201
- schema: method.response,
236
+ schema: ensureZodObject(method.response),
202
237
  messages,
203
238
  enums,
204
239
  typePrefix
@@ -211,7 +246,7 @@ const processServiceMethod = (method, context) => {
211
246
  };
212
247
  };
213
248
  const generateServices = (services, context) => {
214
- return services.map((service) => {
249
+ return normalizeServices(services).map((service) => {
215
250
  const methods = service.methods.map((method) => {
216
251
  const { requestName, responseName } = processServiceMethod(method, context);
217
252
  const requestStreaming = method.streaming === "client" || method.streaming === "bidirectional";
@@ -227,7 +262,7 @@ const generateServices = (services, context) => {
227
262
  //#endregion
228
263
  //#region src/zod-to-protobuf.ts
229
264
  const zodToProtobuf = (schema, options = {}) => {
230
- const { packageName = "default", rootMessageName = "Message", typePrefix = "", services = [], skipRootMessage = false } = options;
265
+ const { packageName = "default", rootMessageName = "Message", typePrefix = "", services, skipRootMessage = false } = options;
231
266
  const messages = /* @__PURE__ */ new Map();
232
267
  const enums = /* @__PURE__ */ new Map();
233
268
  if (schema && !skipRootMessage) {
@@ -247,7 +282,7 @@ const zodToProtobuf = (schema, options = {}) => {
247
282
  enums,
248
283
  typePrefix: typePrefix || null
249
284
  };
250
- if (services.length > 0) generateServices(services, context);
285
+ const servicesString = services && (Array.isArray(services) ? services.length > 0 : Object.keys(services).length > 0) ? generateServices(services, context) : [];
251
286
  return `
252
287
  syntax = "proto3";
253
288
  package ${packageName};
@@ -255,7 +290,7 @@ package ${packageName};
255
290
  ${[
256
291
  Array.from(enums.values()).map((enumDef) => enumDef.join("\n")),
257
292
  Array.from(messages.entries()).map(([name, fields]) => `message ${name} {\n${fields.map((field) => ` ${field}`).join("\n")}\n}`),
258
- services.length > 0 ? generateServices(services, context) : []
293
+ servicesString
259
294
  ].filter((strings) => !!strings.length).map((strings) => strings.join("\n\n")).join("\n\n")}
260
295
  `.trim();
261
296
  };
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["tupleFields: ProtobufField[]"],"sources":["../src/types.ts","../src/utils.ts","../src/traversers.ts","../src/service-generator.ts","../src/zod-to-protobuf.ts"],"sourcesContent":["import type { ZodTypeAny } from \"zod\";\n\nexport interface ZodToProtobufOptions {\n packageName?: string;\n rootMessageName?: string;\n typePrefix?: string;\n services?: ServiceDefinition[];\n skipRootMessage?: boolean;\n}\n\nexport interface ServiceMethod {\n name: string;\n request: ZodTypeAny;\n response: ZodTypeAny;\n streaming?: \"client\" | \"server\" | \"bidirectional\";\n}\n\nexport interface ServiceDefinition {\n name: string;\n methods: ServiceMethod[];\n}\n\nexport class UnsupportedTypeException extends Error {\n constructor(type: string) {\n super(`Unsupported type: ${type}`);\n this.name = \"UnsupportedTypeException\";\n }\n}\n\nexport interface ProtobufField {\n types: Array<string | null>;\n name: string;\n}\n","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 ZodSet,\n ZodString,\n ZodTuple,\n ZodType,\n type ZodTypeAny,\n} from \"zod\";\nimport { UnsupportedTypeException, type ProtobufField } from \"./types\";\nimport { getNumberTypeName, toPascalCase, protobufFieldToType } from \"./utils\";\n\nexport const traverseArray = ({\n key,\n value,\n messages,\n enums,\n typePrefix,\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}): ProtobufField[] => {\n const nestedValue =\n value instanceof ZodArray\n ? value.element\n : value instanceof ZodSet\n ? (value._def as { valueType: ZodTypeAny }).valueType\n : // @ts-expect-error\n (value._def as { element?: ZodTypeAny }).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 });\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}: {\n key: string;\n value: ZodMap<ZodTypeAny, ZodTypeAny>;\n messages: Map<string, string[]>;\n enums: Map<string, string[]>;\n typePrefix: string | null;\n}): ProtobufField[] => {\n const keyType = traverseKey({\n key: `${key}Key`,\n value: value._def.keyType,\n messages,\n enums,\n isOptional: false,\n isInArray: true,\n typePrefix,\n });\n const valueType = traverseKey({\n key: `${key}Value`,\n value: value._def.valueType,\n messages,\n enums,\n isOptional: false,\n isInArray: true,\n typePrefix,\n });\n\n if (!keyType[0] || keyType.length !== 1) {\n throw new UnsupportedTypeException(`${key} map key`);\n }\n\n if (!valueType[0] || valueType.length !== 1) {\n throw new UnsupportedTypeException(`${key} map value`);\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}: {\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}): ProtobufField[] => {\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 });\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 });\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 });\n }\n\n const optional = isOptional && !isInArray ? \"optional\" : null;\n\n if (value instanceof ZodObject) {\n let messageName = toPascalCase({ value: key });\n if (typePrefix) {\n messageName = `${typePrefix}${messageName}`;\n }\n const nestedMessageFields = traverseSchema({\n schema: value,\n messages,\n enums,\n typePrefix,\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 (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 });\n });\n\n const tupleMessageName = toPascalCase({ value: key });\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 throw new UnsupportedTypeException(value.constructor.name);\n }\n\n throw new UnsupportedTypeException(typeof value);\n};\n\nexport const traverseSchema = ({\n schema,\n messages,\n enums,\n typePrefix,\n}: {\n schema: ZodTypeAny;\n messages: Map<string, string[]>;\n enums: Map<string, string[]>;\n typePrefix: string | null;\n}): string[] => {\n if (!(schema instanceof ZodObject)) {\n throw new UnsupportedTypeException(schema.constructor.name);\n }\n\n const fields = Object.entries(schema.shape).flatMap(([key, value]) => {\n return traverseKey({\n key,\n value,\n messages,\n enums,\n isOptional: false,\n isInArray: false,\n typePrefix,\n });\n });\n\n return fields.map(\n (field, index) =>\n `${protobufFieldToType({ field })} ${field.name} = ${index + 1};`,\n );\n};\n","import type { ZodTypeAny } from \"zod\";\nimport type { ServiceDefinition, ServiceMethod } 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 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 requestFields = traverseSchema({\n schema: method.request,\n messages,\n enums,\n typePrefix,\n });\n messages.set(requestName, requestFields);\n }\n\n if (!messages.has(responseName)) {\n const responseFields = traverseSchema({\n schema: method.response,\n messages,\n enums,\n typePrefix,\n });\n messages.set(responseName, responseFields);\n }\n\n return { requestName, responseName };\n};\n\nexport const generateServices = (\n services: ServiceDefinition[],\n context: ServiceGenerationContext\n): string[] => {\n return services.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\";\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 if (services.length > 0) {\n generateServices(services, context);\n }\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 servicesString =\n services.length > 0 ? generateServices(services, context) : [];\n\n const content = [enumsString, messagesString, servicesString]\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/types.ts","../src/utils.ts","../src/traversers.ts","../src/service-generator.ts","../src/zod-to-protobuf.ts"],"sourcesContent":["import type { ZodObject, ZodTypeAny } from \"zod\";\n\nexport type ServicesInput =\n | ServiceDefinition[]\n | Record<string, ZodObject<any>>;\n\nexport interface ZodToProtobufOptions {\n packageName?: string;\n rootMessageName?: string;\n typePrefix?: string;\n services?: ServicesInput;\n skipRootMessage?: boolean;\n}\n\nexport interface ServiceMethod {\n name: string;\n request: ZodTypeAny;\n response: ZodTypeAny;\n streaming?: \"client\" | \"server\" | \"bidirectional\";\n}\n\nexport interface ServiceDefinition {\n name: string;\n methods: ServiceMethod[];\n}\n\nexport class UnsupportedTypeException extends Error {\n constructor(type: string) {\n super(`Unsupported type: ${type}`);\n this.name = \"UnsupportedTypeException\";\n }\n}\n\nexport interface ProtobufField {\n types: Array<string | null>;\n name: string;\n}\n","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 ZodSet,\n ZodString,\n ZodTuple,\n ZodType,\n type ZodTypeAny,\n} from \"zod\";\nimport { UnsupportedTypeException, type ProtobufField } from \"./types\";\nimport { getNumberTypeName, toPascalCase, protobufFieldToType } from \"./utils\";\n\nexport const traverseArray = ({\n key,\n value,\n messages,\n enums,\n typePrefix,\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}): ProtobufField[] => {\n const nestedValue =\n value instanceof ZodArray\n ? value.element\n : value instanceof ZodSet\n ? (value._def as { valueType: ZodTypeAny }).valueType\n : // @ts-expect-error\n (value._def as { element?: ZodTypeAny }).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 });\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}: {\n key: string;\n value: ZodMap<ZodTypeAny, ZodTypeAny>;\n messages: Map<string, string[]>;\n enums: Map<string, string[]>;\n typePrefix: string | null;\n}): ProtobufField[] => {\n const mapDef = (value._def || value.def) as {\n keyType?: ZodTypeAny;\n valueType?: ZodTypeAny;\n };\n\n const keyType = traverseKey({\n key: inflection.singularize(key),\n value:\n mapDef.keyType ||\n (value as ZodTypeAny & { keyType?: ZodTypeAny }).keyType,\n messages,\n enums,\n isOptional: false,\n isInArray: true,\n typePrefix,\n });\n const valueType = traverseKey({\n key: inflection.singularize(key),\n value:\n mapDef.valueType ||\n (value as ZodTypeAny & { valueType?: ZodTypeAny }).valueType,\n messages,\n enums,\n isOptional: false,\n isInArray: true,\n typePrefix,\n });\n\n if (!keyType[0] || keyType.length !== 1) {\n throw new UnsupportedTypeException(`${key} map key`);\n }\n\n if (!valueType[0] || valueType.length !== 1) {\n throw new UnsupportedTypeException(`${key} map value`);\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}: {\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}): 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 });\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 });\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 });\n }\n\n const optional = isOptional && !isInArray ? \"optional\" : null;\n\n if (value instanceof ZodObject) {\n let messageName = toPascalCase({ value: key });\n if (typePrefix) {\n messageName = `${typePrefix}${messageName}`;\n }\n const nestedMessageFields = traverseSchema({\n schema: value,\n messages,\n enums,\n typePrefix,\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 (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 });\n });\n\n const tupleMessageName = toPascalCase({ value: key });\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 throw new UnsupportedTypeException(value.constructor.name);\n }\n\n throw new UnsupportedTypeException(typeof value);\n};\n\nexport const traverseSchema = ({\n schema,\n messages,\n enums,\n typePrefix,\n}: {\n schema: ZodTypeAny;\n messages: Map<string, string[]>;\n enums: Map<string, string[]>;\n typePrefix: string | null;\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 throw new UnsupportedTypeException(\n schema?.constructor?.name || typeof schema\n );\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 });\n });\n\n return fields.map(\n (field, index) =>\n `${protobufFieldToType({ field })} ${field.name} = ${index + 1};`\n );\n};\n","import { z, type ZodFunction, ZodObject, type ZodTypeAny } from \"zod\";\nimport type { ServiceDefinition, ServiceMethod, ServicesInput } 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 {\n type?: string;\n input?: ZodTypeAny;\n output?: ZodTypeAny;\n };\n\n if (methodDef.type === \"function\") {\n const inputDef = methodDef.input as ZodTypeAny & {\n def?: { items?: ZodTypeAny[] };\n };\n\n const args = inputDef?.def?.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 });\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 });\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\";\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 = [enumsString, messagesString, servicesString]\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.5",
3
+ "version": "1.0.7",
4
4
  "author": {
5
5
  "name": "GlobalArt, Inc"
6
6
  },
@@ -26,6 +26,17 @@
26
26
  }
27
27
  }
28
28
  },
29
+ "repository": {
30
+ "type": "git",
31
+ "url": "git+https://github.com/GlobalArtInc/ecosystem.git#main"
32
+ },
33
+ "keywords": [
34
+ "zod",
35
+ "protobuf",
36
+ "grpc",
37
+ "protobuf-schema",
38
+ "protobuf-generator"
39
+ ],
29
40
  "scripts": {
30
41
  "format": "prettier --write \"**/*.ts\"",
31
42
  "test": "jest --runInBand --passWithNoTests",