1.1.1 • Published 9 months ago

safe-event v1.1.1

Weekly downloads
-
License
ISC
Repository
github
Last release
9 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

9 months ago

1.0.30

9 months ago

1.0.29

9 months ago

1.0.28

9 months ago

1.0.27

9 months ago

1.0.26

9 months ago

1.0.25

9 months ago

1.0.24

9 months ago

1.0.23

9 months ago

1.0.22

10 months ago

1.0.21

10 months ago

1.0.20

10 months ago

1.0.19

10 months ago

1.0.18

10 months ago

1.0.17

10 months ago

1.0.16

10 months ago

1.0.15

10 months ago

1.0.14

10 months ago

1.0.13

10 months ago

1.0.12

10 months ago

1.0.11

10 months ago

1.0.10

10 months ago

1.0.9

10 months ago

1.0.8

10 months ago

1.0.7

10 months ago

1.0.6

10 months ago

1.0.5

10 months ago

1.0.4

10 months ago

1.0.3

10 months ago

1.0.2

10 months ago

1.0.1

10 months ago

1.0.0

10 months ago