Zod: Reusing field multiple times

I have a large schema that represents a cluster with many data tiers:

hot
warm
cold
frozen

Each of this properties contains an array of nodes, the content of hot,war,cold,frozen is the same type. I can’t figure out how can I reuse this node type to avoid repeating.

const nodesOut = z.object({
  zone: z.string(),
  hot: z.array(
    z.object({
      jvm: z.object({
        mem: z.object({
          heap_used_in_bytes: z.number(),
          heap_used_percent: z.number(),
        }),
      }),
      fs: z.object({
        total: z.object({
          total_in_bytes: z.number(),
          free_in_bytes: z.number(),
          available_in_bytes: z.number(),
        }),
      }),
      indices: z.object({
        mappings: z.object({
          total_count: z.number(),
          total_estimated_overhead_in_bytes: z.number(),
        }),
      }).optional(),
      attributes: z.object({
        data: z.string().optional(),
        availability_zone: z.string(),
        server_name: z.string(),
      }),
    })
  ).optional(),
  warm: z.array(
    z.object({
      jvm: z.object({
        mem: z.object({
          heap_used_in_bytes: z.number(),
          heap_used_percent: z.number(),
        }),
      }),
      fs: z.object({
        total: z.object({
          total_in_bytes: z.number(),
          free_in_bytes: z.number(),
          available_in_bytes: z.number(),
        }),
      }),
      indices: z.object({
        mappings: z.object({
          total_count: z.number(),
          total_estimated_overhead_in_bytes: z.number(),
        }),
      }).optional(),
      attributes: z.object({
        data: z.string().optional(),
        availability_zone: z.string(),
        server_name: z.string(),
      }),
    })
  ).optional(),
  cold: z.array(
    z.object({
      jvm: z.object({
        mem: z.object({
          heap_used_in_bytes: z.number(),
          heap_used_percent: z.number(),
        }),
      }),
      fs: z.object({
        total: z.object({
          total_in_bytes: z.number(),
          free_in_bytes: z.number(),
          available_in_bytes: z.number(),
        }),
      }),
      indices: z.object({
        mappings: z.object({
          total_count: z.number(),
          total_estimated_overhead_in_bytes: z.number(),
        }).optional(),
      }),
      attributes: z.object({
        data: z.string().optional(),
        availability_zone: z.string(),
        server_name: z.string(),
      }),
    })
  ).optional(),
  frozen: z.array(
    z.object({
      jvm: z.object({
        mem: z.object({
          heap_used_in_bytes: z.number(),
          heap_used_percent: z.number(),
        }),
      }),
      fs: z.object({
        total: z.object({
          total_in_bytes: z.number(),
          free_in_bytes: z.number(),
          available_in_bytes: z.number(),
        }),
      }),
      indices: z.object({
        mappings: z.object({
          total_count: z.number(),
          total_estimated_overhead_in_bytes: z.number(),
        }),
      }).optional(),
      attributes: z.object({
        data: z.string().optional(),
        availability_zone: z.string(),
        server_name: z.string(),
      }),
    })
  ).optional(),
});

I read about recursive schemas but this is not actually recursive. What’s the best way to go?

Thanks

https://github.com/colinhacks/zod#recursive-types