1.1.1 • Published 4 months ago

safe-event v1.1.1

Weekly downloads
-
License
ISC
Repository
github
Last release
4 months ago

safe-event

A TypeScript event generator library that creates strongly-typed event definitions with runtime validation.

Features

  • Generate TypeScript types from JSON schema definitions
  • Runtime validation using ajv
  • Type-safe event payload access
  • Domain-scoped event naming (e.g. "user:profile.updated")
  • Support for dot notation in event names
  • Support for multiple schema files

Installation

npm install safe-event

Quick Start

1. Configuration

After installation, a safe-event.config.json file is created in your project root:

{
  "schemaDir": "./events/schema",
  "outputDir": "./events/generated"
}

2. Define Events

Create event schema files in your schema directory (e.g. events/schema/user-events.json). The schema format follows the Ajv JSON Schema specification:

{
  "domain": "user",
  "events": {
    "role.assigned": {
      "schema": {
        "type": "object",
        "properties": {
          "userId": { "type": "string" },
          "role": {
            "type": "string",
            "enum": ["admin", "editor", "viewer"]
          },
          "assignedBy": { "type": "string" },
          "expiresAt": { "type": "number" }
        },
        "required": ["userId", "role", "assignedBy"],
        "additionalProperties": false
      }
    }
  }
}

3. Generate Types

npx safe-event

Note: Run this command whenever you update your event schemas to regenerate the TypeScript types.

4. Use Generated Types

import {
  userEvents,
  RoleAssignedEventData,
  RoleAssignedEventPayload,
} from "./events/generated/user-events";

// Create type-safe event with validation
const event = RoleAssignedEventData.from({
  userId: "123",
  role: "editor", // Type-safe: only "admin" | "editor" | "viewer" allowed
  assignedBy: "456",
  expiresAt: Date.now() + 86400000,
});

// Get event type string
const eventType = userEvents["role.assigned"]; // "user:role.assigned"

// Type casting example
function handleEvent(type: string, data: any) {
  if (type === userEvents["role.assigned"]) {
    // data is now typed as RoleAssignedEventPayload
    const payload = data as RoleAssignedEventPayload;
    console.log(`${payload.role} role assigned by ${payload.assignedBy}`);
  }
}

EventBus

A simple way to emit and listen to events across your application.

Basic Example

import { EventBus } from "./EventBus";
import {
  UserEvents,
  RoleAssignedEventData,
} from "./events/generated/user-events";

// Initialize
const eventBus = EventBus.init();

// Listen for events
eventBus.onEvent({
  event: UserEvents["role.assigned"],
  callback: (data) => {
    console.log("New role assigned:", data.role);
  },
});

// Emit events
eventBus.emitEvent({
  event: UserEvents["role.assigned"],
  data: RoleAssignedEventData.from({
    userId: "123",
    role: "editor",
    assignedBy: "456",
  }),
});

Advanced Features

Correlation IDs

Use correlation IDs to track related events:

// Emit with correlation ID
eventBus.emitEvent({
  event: UserEvents["role.assigned"],
  data: RoleAssignedEventData.from({
    /* ... */
  }),
  correlationId: "request-123",
});

// Access correlation ID in listener
eventBus.onEvent({
  event: UserEvents["role.assigned"],
  callback: (data, correlationId) => {
    console.log(`Event ${correlationId}:`, data);
  },
});

Buffered Events

Wait for multiple related events before processing:

// Listen for multiple events
eventBus.onDependentEvents({
  events: [UserEvents["profile.created"], UserEvents["role.assigned"]],
  callback: (buffer) => {
    // Access events by their names
    const profile = buffer[UserEvents["profile.created"]];
    const role = buffer[UserEvents["role.assigned"]];
    console.log("User setup complete:", { profile, role });
  },
});

// Emit related events
eventBus.emitEvent({
  event: UserEvents["profile.created"],
  data: ProfileCreatedEventData.from({
    /* ... */
  }),
  correlationId: "request-123",
});

eventBus.emitEvent({
  event: UserEvents["role.assigned"],
  data: RoleAssignedEventData.from({
    /* ... */
  }),
  correlationId: "request-123",
});

One-time Events

Listen for a single occurrence of an event with a specific correlation ID:

eventBus.onceEvent({
  event: UserEvents["role.assigned"],
  correlationId: "request-123",
  callback: (data) => {
    console.log("Role assigned:", data);
    // Listener automatically detaches after this callback
  },
});

License

MIT

1.1.1

4 months ago

1.0.30

4 months ago

1.0.29

4 months ago

1.0.28

4 months ago

1.0.27

4 months ago

1.0.26

4 months ago

1.0.25

4 months ago

1.0.24

4 months ago

1.0.23

4 months ago

1.0.22

5 months ago

1.0.21

5 months ago

1.0.20

5 months ago

1.0.19

5 months ago

1.0.18

5 months ago

1.0.17

5 months ago

1.0.16

5 months ago

1.0.15

5 months ago

1.0.14

5 months ago

1.0.13

5 months ago

1.0.12

5 months ago

1.0.11

5 months ago

1.0.10

5 months ago

1.0.9

5 months ago

1.0.8

5 months ago

1.0.7

5 months ago

1.0.6

5 months ago

1.0.5

5 months ago

1.0.4

5 months ago

1.0.3

5 months ago

1.0.2

5 months ago

1.0.1

5 months ago

1.0.0

5 months ago