Claude Code Plugins

Community-maintained marketplace

Feedback

transforming-string-methods

@djankies/claude-configs
0
0

Write type-safe transformations with Zod including string methods, custom transforms, codecs, and pipelines

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name transforming-string-methods
description Write type-safe transformations with Zod including string methods, custom transforms, codecs, and pipelines

Writing Zod Transformations

Purpose

Comprehensive guide to writing transformations in Zod v4, covering built-in string methods, custom transforms, codecs, and transformation pipelines.

Built-In String Transformations

Trim, Lower Case, Upper Case

const schema = z.string().trim();           // Remove whitespace
const schema = z.string().toLowerCase();    // Convert to lowercase
const schema = z.string().toUpperCase();    // Convert to uppercase

Use cases:

  • Trim: User input fields (always trim)
  • Lower: Email/username normalization
  • Upper: Product codes, currency codes

Chaining:

const emailSchema = z.email().trim().toLowerCase();

Execution order: Transformations execute left-to-right

Best practice: Transform before validation

z.string().trim().min(1)      // ✅ Trim then validate
z.string().min(1).trim()      // ❌ Validate then trim (wrong order)

Custom Transformations

Basic Transform

const schema = z.string().transform(s => s.toUpperCase());

type Input = z.input<typeof schema>;    // string
type Output = z.output<typeof schema>;  // string

Type-Changing Transform

const schema = z.string().transform(s => parseInt(s));

type Input = z.input<typeof schema>;    // string
type Output = z.output<typeof schema>;  // number

Transform with Validation

const schema = z.string()
  .regex(/^\d+$/, { error: "Must be numeric string" })
  .transform(s => parseInt(s))
  .refine(n => n > 0, { error: "Must be positive" });

Order: Validation → Transformation → Refinement

Transform Objects

const userSchema = z.object({
  firstName: z.string(),
  lastName: z.string()
}).transform(user => ({
  ...user,
  fullName: `${user.firstName} ${user.lastName}`
}));

Transform Arrays

const schema = z.string()
  .transform(s => s.split(','))
  .transform(arr => arr.map(s => s.trim()))
  .transform(arr => arr.filter(s => s.length > 0));

Codecs (Bidirectional Transforms)

Date Codec

const dateCodec = z.codec({
  decode: z.iso.datetime().transform(s => new Date(s)),
  encode: z.date().transform(d => d.toISOString())
});

const decoded = dateCodec.parse('2024-01-01T00:00:00Z');  // Date object
const encoded = dateCodec.encode(new Date('2024-01-01'));  // string

Safe Codec

const result = dateCodec.safeDecode('invalid-date');
if (!result.success) {
  console.error(result.error);
}

Base64 Codec

const base64Codec = z.codec({
  decode: z.base64().transform(s => Buffer.from(s, 'base64')),
  encode: z.instanceof(Buffer).transform(b => b.toString('base64'))
});

Transformation Pipelines

Sequential Transformations

const schema = z.string()
  .trim()
  .toLowerCase()
  .transform(s => s.split(' '))
  .transform(words => words.filter(w => w.length > 0))
  .transform(words => words.join('-'));

Pipe Method

const stringToNumber = z.string()
  .regex(/^\d+$/)
  .transform(s => parseInt(s));

const positiveNumber = z.number().min(1);

const schema = stringToNumber.pipe(positiveNumber);

Type inference:

type Input = z.input<typeof schema>;    // string
type Output = z.output<typeof schema>;  // number

Overwrite vs Transform

Transform (additive):

z.object({ firstName, lastName }).transform(data => ({
  ...data,
  fullName: `${data.firstName} ${data.lastName}`
}));

Output has all fields: firstName, lastName, fullName

Overwrite (destructive):

z.object({ firstName, lastName }).overwrite(data => ({
  fullName: `${data.firstName} ${data.lastName}`
}));

Output has only new fields: fullName

Async Transformations

Basic Async Transform

const schema = z.string().transform(async (email) => {
  const user = await fetchUser(email);
  return user;
});

const result = await schema.parseAsync('user@example.com');

Async Refinement

const emailSchema = z.email().refine(
  async (email) => {
    const exists = await checkEmailExists(email);
    return !exists;
  },
  { error: "Email already exists" }
);

Best Practices

1. Transform Before Validation

z.string().trim().min(1)      // ✅ Trim then validate
z.string().min(1).trim()      // ❌ Validate then trim

2. Use Built-In Methods

z.string().trim().toLowerCase()              // ✅ Built-in
z.string().transform(s => s.trim().toLowerCase())  // ❌ Manual

3. Keep Transformations Pure

const schema = z.string().transform(s => s.toUpperCase());  // ✅ Pure

let count = 0;
const schema = z.string().transform(s => {
  count++;  // ❌ Side effect
  return s.toUpperCase();
});

4. Use Codecs for Serialization

const dateCodec = z.codec({
  decode: z.iso.datetime().transform(s => new Date(s)),
  encode: z.date().transform(d => d.toISOString())
});  // ✅ Bidirectional

5. Type-Safe Transformations

const schema = z.string().transform(s => parseInt(s));
type Output = z.output<typeof schema>;  // ✅ Type-safe

6. Handle Edge Cases

const schema = z.string()
  .transform(s => s.split(','))
  .transform(arr => arr.map(s => s.trim()))
  .transform(arr => arr.filter(s => s.length > 0));  // ✅ Handle empty

Migration from v3

String Transformations (New in v4):

const validated = z.string().trim().parse(input);  // ✅ v4 declarative

Codecs (New in v4):

const codec = z.codec({
  decode: z.iso.datetime().transform(s => new Date(s)),
  encode: z.date().transform(d => d.toISOString())
});  // ✅ v4 bidirectional

References

  • v4 Features: Use the validating-string-formats skill from the zod-4 plugin
  • Error handling: Use the customizing-errors skill from the zod-4 plugin
  • Performance: Use the optimizing-performance skill from the zod-4 plugin
  • Testing: Use the testing-zod-schemas skill from the zod-4 plugin

Success Criteria

  • ✅ Using built-in string transformations
  • ✅ Transform before validation
  • ✅ Pure transformation functions
  • ✅ Type-safe with z.input/z.output
  • ✅ Codecs for bidirectional transforms
  • ✅ Proper transformation order
  • ✅ Edge cases handled
  • ✅ Performance optimized