add-resource-events
Add real-time event emission to a resource service. Use when adding SSE/real-time capabilities to a resource. Triggers on "add events", "real-time events", "SSE events".
Best use case
add-resource-events is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Add real-time event emission to a resource service. Use when adding SSE/real-time capabilities to a resource. Triggers on "add events", "real-time events", "SSE events".
Teams using add-resource-events should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/add-resource-events/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How add-resource-events Compares
| Feature / Agent | add-resource-events | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Add real-time event emission to a resource service. Use when adding SSE/real-time capabilities to a resource. Triggers on "add events", "real-time events", "SSE events".
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# Add Resource Events
Enables real-time event emission for a resource service via Server-Sent Events (SSE).
## Quick Reference
**Event Infrastructure**:
- `src/events/event-emitter.ts` - Singleton `AppEventEmitter`
- `src/events/base.service.ts` - `BaseService` with `emitEvent()`
- `src/schemas/event.schema.ts` - Event type definitions
- `src/routes/events.router.ts` - SSE endpoint
**Event Pattern**: `{serviceName}:{action}` (e.g., `notes:created`, `notes:updated`)
## Prerequisites
To add events to a resource:
1. Service must extend `BaseService` (see `create-resource-service`)
2. Authorization methods for events in `AuthorizationService`
## How It Works
### 1. BaseService Provides emitEvent()
```typescript
// src/events/base.service.ts
export abstract class BaseService {
constructor(protected serviceName: string) {}
protected emitEvent<T>(
action: ServiceEventType["action"],
data: T,
options?: {
id?: string;
user?: { userId: string; [key: string]: unknown };
},
) {
appEvents.emitServiceEvent(this.serviceName, {
id: options?.id || uuidv4(),
action,
data,
user: eventUser,
timestamp: new Date(),
resourceType: this.serviceName,
});
}
}
```
### 2. Resource Service Emits Events
```typescript
export class NoteService extends BaseService {
constructor(...) {
super("notes"); // Service name for event routing
}
async create(data, user) {
// ... create logic ...
this.emitEvent("created", note, { id: note.id, user });
return note;
}
async update(id, data, user) {
// ... update logic ...
this.emitEvent("updated", updatedNote, { id: updatedNote.id, user });
return updatedNote;
}
async delete(id, user) {
// ... delete logic ...
this.emitEvent("deleted", note, { id: note.id, user });
return true;
}
}
```
### 3. Events Router Streams to Clients
```typescript
// src/routes/events.router.ts
appEvents.on("notes:created", eventHandler);
appEvents.on("notes:updated", eventHandler);
appEvents.on("notes:deleted", eventHandler);
```
## Adding Events to a New Resource
### Step 1: Extend BaseService
Your service must extend `BaseService`:
```typescript
import { BaseService } from "@/events/base.service";
export class {Entity}Service extends BaseService {
constructor(...) {
super("{entities}"); // Plural for event namespace
}
}
```
### Step 2: Emit Events in CRUD Methods
Add `emitEvent()` calls after successful operations:
```typescript
async create(data, user) {
const {entity} = await this.repository.create(data, user.userId);
this.emitEvent("created", {entity}, { id: {entity}.id, user });
return {entity};
}
async update(id, data, user) {
const updated = await this.repository.update(id, data);
if (!updated) return null;
this.emitEvent("updated", updated, { id: updated.id, user });
return updated;
}
async delete(id, user) {
const {entity} = await this.repository.findById(id);
const deleted = await this.repository.remove(id);
if (deleted) {
this.emitEvent("deleted", {entity}, { id: {entity}.id, user });
}
return deleted;
}
```
### Step 3: Add Event Authorization
In `src/services/authorization.service.ts`:
```typescript
async canReceive{Entity}Event(
user: AuthenticatedUserContextType,
{entity}Data: { createdBy: string; [key: string]: unknown },
): Promise<boolean> {
if (this.isAdmin(user)) return true;
if ({entity}Data.createdBy === user.userId) return true;
return false;
}
```
### Step 4: Update Events Router
In `src/routes/events.router.ts`, add listeners:
```typescript
// Listen to {entity} events
appEvents.on("{entities}:created", eventHandler);
appEvents.on("{entities}:updated", eventHandler);
appEvents.on("{entities}:deleted", eventHandler);
```
Update the `shouldUserReceiveEvent` function:
```typescript
async function shouldUserReceiveEvent(
event: ServiceEventType,
user: AuthenticatedUserContextType,
authorizationService: AuthorizationService,
): Promise<boolean> {
switch (event.resourceType) {
case "notes":
// ... existing ...
case "{entities}":
if (
typeof event.data === "object" &&
event.data !== null &&
"createdBy" in event.data
) {
return await authorizationService.canReceive{Entity}Event(
user,
event.data as { createdBy: string; [key: string]: unknown },
);
}
return false;
default:
return false;
}
}
```
### Step 5: Add Event Schema (Optional)
In `src/schemas/event.schema.ts`:
```typescript
export const {entity}EventSchema = serviceEventSchema.extend({
data: z.object({
id: z.string(),
// ... entity-specific fields
createdAt: z.date().optional(),
updatedAt: z.date().optional(),
}),
});
export type {Entity}EventType = z.infer<typeof {entity}EventSchema>;
```
## Event Flow
```
1. Client: POST /notes (create a note)
2. Controller: calls NoteService.create()
3. Service: creates note, calls this.emitEvent("created", note, ...)
4. BaseService: appEvents.emitServiceEvent("notes", { action: "created", ... })
5. EventEmitter: emits "notes:created" event
6. Events Router: catches event, checks authorization
7. SSE Stream: sends to authorized clients
8. Client: receives { event: "notes:created", data: {...} }
```
## Client-Side Usage
```javascript
const eventSource = new EventSource("/events", {
headers: { Authorization: `Bearer ${token}` },
});
eventSource.addEventListener("notes:created", (event) => {
const data = JSON.parse(event.data);
console.log("New note:", data);
});
eventSource.addEventListener("notes:updated", (event) => {
const data = JSON.parse(event.data);
console.log("Updated note:", data);
});
eventSource.addEventListener("notes:deleted", (event) => {
const data = JSON.parse(event.data);
console.log("Deleted note:", data);
});
```
## What NOT to Do
- Do NOT emit events before confirming operation succeeded
- Do NOT emit events for failed/unauthorized operations
- Do NOT skip authorization checks in events router
- Do NOT forget to clean up event listeners on disconnect
## See Also
- `create-resource-service` - Creating services with event emission
- `create-routes` - Events router example
- `test-resource-service` - Testing event emissionRelated Skills
analytics-events
Add product analytics events to track user interactions in the Metabase frontend
events-webinars
Use this skill when a VP of Events or field marketing leader needs to plan and execute the full events program — including webinars, technology workshops, solution workshops, global speaking engagements, conferences, and community events — capturing leads, filling the sales calendar post-event, and building market presence with investors, enterprise buyers, and practitioners.
symfony:api-platform-resources
Use when symfony api platform resources
symfony:api-platform-dto-resources
Use when symfony api platform dto resources
newsletter-events-write
Generate markdown newsletters from stored events. Use when the user wants to create, write, or generate a newsletter from scraped events.
microsoft-azure-webjobs-extensions-authentication-events-dotnet
Microsoft Entra Authentication Events SDK for .NET. Azure Functions triggers for custom authentication extensions.
azure-resource-manager-sql-dotnet
Azure Resource Manager SDK for Azure SQL in .NET.
azure-resource-manager-redis-dotnet
Azure Resource Manager SDK for Redis in .NET.
azure-resource-manager-postgresql-dotnet
Azure PostgreSQL Flexible Server SDK for .NET. Database management for PostgreSQL Flexible Server deployments.
azure-resource-manager-mysql-dotnet
Azure MySQL Flexible Server SDK for .NET. Database management for MySQL Flexible Server deployments.
api-resource-patterns
Best practices for Laravel API Resources including resource transformation, collection handling, conditional attributes, and relationship loading.
ado-resource-validator
Validates Azure DevOps projects, area paths, and teams exist with auto-creation of missing resources. Use when setting up ADO integration, configuring .env variables, or troubleshooting missing project errors. Supports project-per-team, area-path-based, and team-based strategies.