
create-transformer
by elbwalker
Open-source tag manager for developers
SKILL.md
name: create-transformer description: Use when creating a new walkerOS transformer. Example-driven workflow for validation, enrichment, or redaction transformers.
Create a New Transformer
Prerequisites
Before starting, read these skills:
- understanding-flow - How transformers fit in architecture
- understanding-transformers - Transformer interface
- understanding-events - Event structure
- testing-strategy - How to test
- writing-documentation - Documentation standards (for Phase 6)
Transformer Categories
| Category | Purpose | Example |
|---|---|---|
| Validate | Check event structure/content | JSON Schema, required fields |
| Enrich | Add data to events | Server timestamps, geo data |
| Redact | Remove/mask sensitive data | Strip PII, anonymize IPs |
Process Overview
1. Research → Understand use case (validate/enrich/redact)
2. Examples → Create event before/after examples FIRST
3. Scaffold → Copy template, configure package.json
4. Implement → Build transformer with TDD
5. Test → Verify against example transformations
6. Document → Write README
Phase 1: Research
Goal: Understand what the transformer needs to do.
1.1 Define Use Case
- Category: Validate, Enrich, or Redact?
- Input: What events will this process?
- Output: What should change? What should be blocked?
- Configuration: What settings does user need?
1.2 Check Existing Patterns
# Reference implementation
ls packages/transformers/validator/
# Transformer types
cat packages/core/src/types/transformer.ts
Gate: Research Complete
- Category identified (validate/enrich/redact)
- Input/output transformation defined
- Configuration options listed
Phase 2: Create Examples (BEFORE Implementation)
Goal: Define event transformations in dev entry FIRST.
2.1 Scaffold Directory Structure
mkdir -p packages/transformers/[name]/src/{examples,schemas,types}
2.2 Create Event Examples
Events before and after processing:
src/examples/events.ts:
import type { WalkerOS } from '@walkeros/core';
/**
* Example events for testing transformer behavior.
*/
// Event that should pass through modified
export const validEvent: WalkerOS.DeepPartialEvent = {
event: 'product view',
data: {
id: 'P-123',
name: 'Widget',
email: 'user@example.com', // Sensitive - should be redacted
},
};
// Expected output after processing
export const processedEvent: WalkerOS.DeepPartialEvent = {
event: 'product view',
data: {
id: 'P-123',
name: 'Widget',
// email removed by redaction
},
};
// Event that should be blocked
export const invalidEvent: WalkerOS.DeepPartialEvent = {
event: 'product view',
data: {
// Missing required 'id' field
name: 'Widget',
},
};
2.3 Create Config Examples
src/examples/config.ts:
import type { Transformer } from '@walkeros/core';
/**
* Example configurations for testing.
*/
export const defaultConfig: Transformer.Config = {
settings: {
fieldsToRedact: ['email', 'phone'],
},
};
export const strictConfig: Transformer.Config = {
settings: {
fieldsToRedact: ['email', 'phone', 'ip'],
logRedactions: true,
},
};
2.4 Export via dev.ts
src/dev.ts:
export * as schemas from './schemas';
export * as examples from './examples';
Gate: Examples Valid
- All example files compile (
npm run build) - Can trace: input event → expected output for each example
Phase 3: Scaffold
Template transformer: packages/transformers/validator/
cp -r packages/transformers/validator packages/transformers/[name]
cd packages/transformers/[name]
# Update package.json: name, description, repository.directory
Directory structure:
packages/transformers/[name]/
├── src/
│ ├── index.ts # Main export
│ ├── transformer.ts # Transformer implementation
│ ├── index.test.ts # Tests against examples
│ ├── dev.ts # Exports schemas and examples
│ ├── examples/
│ │ ├── index.ts # Re-exports
│ │ ├── events.ts # Before/after event examples
│ │ └── config.ts # Configuration examples
│ ├── schemas/
│ │ └── index.ts # Zod schemas for settings
│ └── types/
│ └── index.ts # Settings, Types interfaces
├── package.json
├── tsconfig.json
├── tsup.config.ts
├── jest.config.mjs
└── README.md
Phase 4: Implement
Now write code to transform examples as expected.
4.1 Define Types
src/types/index.ts:
import type { Transformer } from '@walkeros/core';
export interface Settings {
fieldsToRedact?: string[];
logRedactions?: boolean;
}
export interface Types extends Transformer.Types<Settings> {}
4.2 Implement Transformer (Context Pattern)
Transformers use the context pattern - they receive a single context
object containing config, env, logger, id, and collector.
src/transformer.ts:
import type { Transformer } from '@walkeros/core';
import type { Settings, Types } from './types';
import { SettingsSchema } from './schemas';
/**
* Transformer initialization using context pattern.
*
* @param context - Transformer context containing:
* - config: Transformer configuration (settings)
* - env: Environment object
* - logger: Logger instance
* - id: Unique transformer identifier
* - collector: Collector instance reference
* - ingest: Optional request metadata from source
*/
export const transformerRedact: Transformer.Init<Types> = (context) => {
// Destructure what you need from context
const { config = {} } = context;
// Validate and apply default settings using Zod schema
const settings = SettingsSchema.parse(config.settings || {});
const fullConfig: Transformer.Config<Types> = {
...config,
settings,
};
return {
type: 'redact',
config: fullConfig,
/**
* Process event - receives event and push context.
*
* @param event - The event to process
* @param pushContext - Context for this specific push operation
* @returns event - continue with modified event
* @returns void - continue with current event unchanged
* @returns false - stop chain, cancel further processing
*/
push(event, pushContext) {
const { logger } = pushContext;
const fields = settings.fieldsToRedact || [];
for (const field of fields) {
if (event.data?.[field] !== undefined) {
delete event.data[field];
if (settings.logRedactions) {
logger?.debug('Redacted field', { field });
}
}
}
return event;
},
};
};
Key patterns:
- Context destructuring: Extract
config,logger,idfrom init context - Schema validation: Use Zod schemas to validate settings and provide defaults
- Push receives pushContext: The
pushfunction gets event + push context - Return values:
event(continue),void(passthrough),false(cancel)
4.3 Export
src/index.ts:
export { transformerRedact } from './transformer';
export type { Settings, Types } from './types';
Gate: Implementation Compiles
-
npm run buildpasses -
npm run lintpasses
Phase 5: Test Against Examples
Verify implementation produces expected outputs.
5.1 Test Helper Pattern
Create a helper to build transformer context for tests:
src/__tests__/index.test.ts:
import { transformerRedact } from '../transformer';
import type { Transformer, Collector } from '@walkeros/core';
import { createMockLogger } from '@walkeros/core';
import type { Types } from '../types';
import { examples } from '../dev';
// Helper to create transformer context for testing
function createTransformerContext(
config: Partial<Transformer.Config<Types>> = {},
): Transformer.Context<Types> {
return {
config,
env: {} as Types['env'],
logger: createMockLogger(),
id: 'test-redact',
collector: {} as Collector.Instance,
};
}
// Helper to create push context for testing
function createPushContext(): Transformer.Context<Types> {
return {
config: {},
env: {} as Types['env'],
logger: createMockLogger(),
id: 'test-redact',
collector: {} as Collector.Instance,
};
}
describe('Redact Transformer', () => {
let mockLogger: ReturnType<typeof createMockLogger>;
beforeEach(() => {
mockLogger = createMockLogger();
});
test('redacts specified fields from valid event', () => {
const transformer = transformerRedact(
createTransformerContext({
settings: { fieldsToRedact: ['email'] },
}),
);
const event = structuredClone(examples.events.validEvent);
const pushContext = createPushContext();
const result = transformer.push(event, pushContext);
expect(result).toMatchObject(examples.events.processedEvent);
expect((result as any).data.email).toBeUndefined();
});
test('passes through event when no fields match', () => {
const transformer = transformerRedact(
createTransformerContext({
settings: { fieldsToRedact: ['ssn'] },
}),
);
const event = structuredClone(examples.events.validEvent);
const pushContext = createPushContext();
const result = transformer.push(event, pushContext);
expect((result as any).data.email).toBe('user@example.com');
});
test('logs redactions when enabled', () => {
const transformer = transformerRedact(
createTransformerContext({
settings: {
fieldsToRedact: ['email'],
logRedactions: true,
},
}),
);
const event = structuredClone(examples.events.validEvent);
const pushContext = {
...createPushContext(),
logger: mockLogger,
};
transformer.push(event, pushContext);
expect(mockLogger.debug).toHaveBeenCalledWith('Redacted field', {
field: 'email',
});
});
});
5.2 Key Test Patterns
- Use
createTransformerContext()helper - Standardizes init context creation - Use
createPushContext()helper - Standardizes push context creation - Use examples for test data - Don't hardcode test values
- Test return values - Verify
event,void, orfalsereturns
Gate: Tests Pass
-
npm run testpasses - Tests verify against example outputs
Phase 6: Document
Follow the writing-documentation skill for:
- README structure and templates
- Quality checklist before publishing
Key requirements for transformer documentation:
- Use case description (validate/enrich/redact)
- Configuration options table
- Working code example with imports
- Installation instructions
- Link to website docs
Transformer-Specific Validation
Beyond understanding-development
requirements (build, test, lint, no any):
-
dev.tsexportsschemasandexamples - Examples include before/after event pairs
- Return values handle all cases (event, void, false)
- Tests use examples for assertions (not hardcoded values)
Reference Files
| What | Where |
|---|---|
| Template | packages/transformers/validator/ |
| Types | packages/core/src/types/transformer.ts |
| Chaining logic | packages/collector/src/transformer.ts |
Related
Score
Total Score
Based on repository quality metrics
SKILL.mdファイルが含まれている
ライセンスが設定されている
100文字以上の説明がある
GitHub Stars 100以上
1ヶ月以内に更新
10回以上フォークされている
オープンIssueが50未満
プログラミング言語が設定されている
1つ以上のタグが設定されている
Reviews
Reviews coming soon

