500-angular-pipes

500-angular-pipes is a cursor rule for Cursor from JrPribs/SmarterStarter. It costs 2 tokens per session (1,646 once invoked), scanned A, original, MIT.

A set of recommended practices for writing Angular pipes, which are reusable functions that transform values for display in templates.

In plain words
What is it for?
Use it when creating standalone pipes for tasks such as truncating text, sorting values, or filtering lists.
Why use it?
It helps keep value transformations predictable and avoids unnecessary work that can make an Angular application slower.

Cursor rule for Cursor

Install

Getting it into your agent

One page per mod, every tool's command on it. A separate URL per tool would split the same page into five that compete with each other.

agentmods
npx agentmods add rules/jrpribs/smarterstarter/500-angular-pipes
Clone the repo
git clone --depth 1 https://github.com/JrPribs/SmarterStarter

Made for: Cursor.

Wrote this? Show the measurements

A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.

agentmods badge for 500-angular-pipes

README.md
[![agentmods](https://agentmods.dev/badge/rules/jrpribs/smarterstarter/500-angular-pipes.svg)](https://agentmods.dev/rules/jrpribs/smarterstarter/500-angular-pipes)
Your own site
<a href="https://agentmods.dev/rules/jrpribs/smarterstarter/500-angular-pipes"><img src="https://agentmods.dev/badge/rules/jrpribs/smarterstarter/500-angular-pipes.svg" alt="Measured on agentmods" height="20"></a>
Per session 2 Only the description is in the session, so the agent can decide to use it. The body loads when it is invoked.
When invoked 1,646 The whole file, excluding the scripts and references it only reads on demand.
Security scan A 0 findings. Scan, not verified.
Origin original No closer match found in the catalogue.
Token cost

What it costs to keep this loaded

Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.

ModelPer sessionOnce invoked
Fable 5 $0.00002 $0.01646
Opus 5 $0.00001 $0.00823
Sonnet 5 $0.00000 $0.00329
Haiku 4.5 $0.00000 $0.00165

Measured 4d ago against content hash 3dbdc2172679, method: parsed. Prices are Anthropic first-party input rates as of 2026-08-30, from the pricing page.

Security

Grade A, and why

500-angular-pipes scanned grade A with 0 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 4d ago.

A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.

Nothing flagged

None of the 26 patterns this scan looks for appear in this file: no shell pipes, no recursive deletes, no credential paths, no hidden text, no instruction-override or anti-refusal phrasing, no agent-config snooping. That is not a guarantee, it is the absence of the things that are checkable.

.cursor/rules/500-angular-pipes.mdc · 246 lines

How it starts

The opening of the file, as written. The whole thing — 246 lines — stays where its author put it; the contents beside it link to each section on GitHub.

Angular Pipes Best Practices

  • Standalone Pipes: Create pipes as standalone to avoid NgModule configuration.
@Pipe({
  name: 'truncate',
  standalone: true
})
export class TruncatePipe implements PipeTransform {
  transform(value: string, limit: number = 100, completeWords: boolean = false, ellipsis: string = '...'): string {
    if (!value) return '';
    if (value.length <= limit) return value;
    
    if (completeWords) {
      limit = value.substring(0, limit).lastIndexOf(' ');
    }
    
    return value.substring(0, limit) + ellipsis;
  }
}
  • Pure Pipes: Keep pipes pure by default. Only use impure pipes when absolutely necessary.
// Pure pipe (default)
@Pipe({
  name: 'sort',
  standalone: true
})
export class SortPipe implements PipeTransform {
  transform<T>(array: T[], property: keyof T): T[] {
    if (!array || !property) return array;
    return [...array].sort((a, b) => {
      const aValue = a[property];
      const bValue = b[property];
      return aValue < bValue ? -1 : aValue > bValue ? 1 : 0;
    });
  }
}

// Impure pipe (only when needed)
@Pipe({
  name: 'filterBy',
  standalone: true,
  pure: false // Impure pipe, will run on every change detection cycle
})
export class FilterPipe implements PipeTransform {
  transform<T>(items: T[], property: keyof T, value: any): T[] {
    if (!items || !property) return items;
    return items.filter(item => item[property] === value);
  }
}
  • Pipe Naming: Use lowerCamelCase for pipe names and use a descriptive name that indicates the pipe's function.
// Good pipe names
name: 'truncate'
name: 'fileSize'
name: 'dateTimeFormat'

// Avoid generic names
name: 'format' // Too generic
name: 'convert' // Unclear purpose
  • Type Safety: Use TypeScript generics to make pipes type-safe.
@Pipe({
  name: 'pluck',
  standalone: true
})
export class PluckPipe implements PipeTransform {
  transform<T, K extends keyof T>(input: T[], key: K): T[K][] {
    if (!input || !Array.isArray(input) || !key) return [];
    return input.map(value => value[key]);
  }
}
  • Pipe Performance: Be mindful of performance, especially with large data sets. Consider caching results or using memoization for expensive transformations.
@Pipe({
  name: 'expensiveTransform',
  standalone: true
})
export class ExpensiveTransformPipe implements PipeTransform {
  private lastValue: any;
  private lastResult: any;
  
  transform(value: any): any {
    // Simple memoization to avoid recalculating for the same input
    if (value === this.lastValue) {
      return this.lastResult;
    }
    
    this.lastValue = value;
    this.lastResult = this.performExpensiveCalculation(value);
    return this.lastResult;
  }
  
  private performExpensiveCalculation(value: any): any {
    // Complex transformation logic here
    return value;
  }
}
  • Chaining Pipes: Design pipes that can be easily chained with other pipes. Focus on a single transformation per pipe.
<!-- Good pipe chaining example in template -->
{{ user.created | date:'short' | uppercase }}
  • Documentation: Document pipe parameters clearly using JSDoc so that developers can easily understand how to use them.
/**
 * Truncates text to a specified length and adds an ellipsis.
 * 
 * @param value - The string to truncate
 * @param limit - Maximum string length (default: 100)
 * @param completeWords - Whether to keep complete words (default: false)
 * @param ellipsis - String to add at the end (default: '...')
 * 
 * @example
 * {{ 'This is a long text' | truncate:10:true }}
 * Output: "This is..."
 * 
 * @return Truncated string
 */
@Pipe({
  name: 'truncate',
  standalone: true
})
export class TruncatePipe implements PipeTransform {
  // Implementation
}
  • Testing Pipes: Create thorough unit tests for pipes, testing various input combinations and edge cases.
describe('TruncatePipe', () => {
  let pipe: TruncatePipe;
  
  beforeEach(() => {
    pipe = new TruncatePipe();
  });
  
  it('should truncate text if over specified limit', () => {
    expect(pipe.transform('This is a test string', 10)).toBe('This is a ...');
  });
  
  it('should not truncate text if under specified limit', () => {
    expect(pipe.transform('Short', 10)).toBe('Short');
  });
  
  it('should respect the completeWords flag', () => {
    expect(pipe.transform('This is a test string', 10, true)).toBe('This is ...');
  });
  
  it('should use custom ellipsis', () => {
    expect(pipe.transform('This is a test string', 10, false, '***')).toBe('This is a ***');
  });
  
  it('should handle null or undefined values', () => {
    expect(pipe.transform(null as any)).toBe('');
    expect(pipe.transform(undefined as any)).toBe('');
  });
});

Read the full file on GitHub · 246 lines

Changes

What this file has done since we first saw it

Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.

  1. 4d ago First seen · 246 lines · 2 tokens per session scan A 3dbdc2172679

Subscribe to this mod's changes

500-angular-pipes is a cursor rule published in the GitHub repository JrPribs/SmarterStarter (2 stars, last pushed 1y ago), licensed MIT. It adds 2 tokens to every session and 1,646 once invoked, about $0.0000 per session on Opus 5. A static security scan graded it A with 0 findings. No closer match exists in the catalogue, so it is treated as the original; first seen 2026-08-31.