Real World Example

Indian Formats: PIN Code and GSTIN

Indian e-commerce and invoicing apps (Zoho Books, ClearTax, Meesho seller panel) validate PIN codes and GST numbers on many routes. Small reusable pipes keep controllers clean.

src/common/pipes/gstin.pipe.ts

import { BadRequestException, Injectable, PipeTransform } from '@nestjs/common';

const GSTIN = /^[0-3][0-9][A-Z]{5}[0-9]{4}[A-Z][1-9A-Z]Z[0-9A-Z]$/;

@Injectable()
export class GstinPipe implements PipeTransform<string, string> {
  transform(value: string): string {
    const gstin = (value ?? '').toUpperCase().trim();
    if (!GSTIN.test(gstin)) throw new BadRequestException('Invalid GSTIN');
    return gstin;
  }
}

// sellers.controller.ts
// @Get('gst/:gstin') findByGst(@Param('gstin', GstinPipe) gstin: string) { ... }

Example

The validation logic itself, tested with a few inputs:

const GSTIN = /^[0-3][0-9][A-Z]{5}[0-9]{4}[A-Z][1-9A-Z]Z[0-9A-Z]$/;
const PIN = /^[1-9][0-9]{5}$/;

function gstinPipe(value: string): string {
  const v = value.toUpperCase().trim();
  if (!GSTIN.test(v)) throw new Error('400 Invalid GSTIN');
  return v;
}

for (const input of ['29abcde1234f1z5', '27AAPFU0939F1ZV', '99XYZ']) {
  try { console.log(input, '->', gstinPipe(input)); } catch (e) { console.log(input, '->', (e as Error).message); }
}
for (const pin of ['560001', '056001', '11000']) console.log('PIN', pin, PIN.test(pin) ? 'valid' : 'invalid');

Output

29abcde1234f1z5 -> 29ABCDE1234F1Z5
27AAPFU0939F1ZV -> 27AAPFU0939F1ZV
99XYZ -> 400 Invalid GSTIN
PIN 560001 valid
PIN 056001 invalid
PIN 11000 invalid