{"_id":"@artflarex-solutions/reservo","name":"@artflarex-solutions/reservo","dist-tags":{"latest":"1.0.0"},"versions":{"1.0.0":{"name":"@artflarex-solutions/reservo","version":"1.0.0","description":"Lightweight appointment management library for Node.js","main":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","require":"./dist/index.js","import":"./dist/index.mjs"},"./transports/smtp":{"types":"./dist/transports/smtp.d.ts","require":"./dist/transports/smtp.js","import":"./dist/transports/smtp.mjs"}},"scripts":{"build":"tsup","test":"node --test --import tsx src/**/*.test.ts","typecheck":"tsc --noEmit","prepublishOnly":"npm run build"},"keywords":["appointment","scheduling","booking","calendar","reservation"],"author":"","license":"MIT","engines":{"node":">=18.0.0"},"devDependencies":{"@types/node":"^20.10.0","tsup":"^8.0.0","tsx":"^4.21.0","typescript":"^5.3.0"},"peerDependencies":{"nodemailer":"^6.0.0"},"peerDependenciesMeta":{"nodemailer":{"optional":true}},"_id":"@artflarex-solutions/reservo@1.0.0","gitHead":"2dd84140dcf7460959f134368a6e173e3a02a687","_nodeVersion":"22.16.0","_npmVersion":"11.4.2","dist":{"integrity":"sha512-WHRHT5keQXuuY2e53csTsMyCkGh0rm+Vw7EdRAWTG7Yf4cdMeMqSpFbBm2ZsrbAgm4ljjuz48C8LOQl2Y/OdUA==","shasum":"32c1c4e36b5ca7f4fcab6656bbb7d9d2baf2ef48","tarball":"https://registry.npmjs.org/@artflarex-solutions/reservo/-/reservo-1.0.0.tgz","fileCount":17,"unpackedSize":101474,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCB1guY2XLX5EDOgmA+bUkKKPLVpF2P09o+fd8Yr92hIAIhANq4KurjbUFIvEHd1wVX4RWBJ2xNyILF67jygolts7uO"}]},"_npmUser":{"name":"artflarex","email":"info@artflarex.com"},"directories":{},"maintainers":[{"name":"artflarex","email":"info@artflarex.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/reservo_1.0.0_1769277161817_0.5932745224030431"},"_hasShrinkwrap":false}},"time":{"created":"2026-01-24T17:52:41.761Z","1.0.0":"2026-01-24T17:52:41.945Z","modified":"2026-01-24T17:52:42.154Z"},"maintainers":[{"name":"artflarex","email":"info@artflarex.com"}],"description":"Lightweight appointment management library for Node.js","keywords":["appointment","scheduling","booking","calendar","reservation"],"license":"MIT","readme":"# Reservo\n\nLightweight appointment management for Node.js applications.\n\nReservo is an infrastructure-level library for managing appointments programmatically. It handles appointment lifecycle, storage, and optional notifications—without imposing UI, authentication, or business logic.\n\n```typescript\nimport { createManager } from 'reservo';\n\nconst manager = createManager();\n\nconst appointment = await manager.createAppointment({\n  title: 'Team Standup',\n  startsAt: new Date('2024-01-15T09:00:00Z'),\n  endsAt: new Date('2024-01-15T09:30:00Z'),\n});\n\nawait manager.confirmAppointment(appointment.id);\n```\n\n## Installation\n\n```bash\nnpm install reservo\n```\n\n## Features\n\n- **TypeScript-first** with full type definitions\n- **Zero dependencies** in core\n- **UTC by default** for predictable time handling\n- **Explicit lifecycle** with enforced state transitions\n- **Pluggable storage** (in-memory default, bring your own adapter)\n- **Pluggable transports** for notifications (SMTP, webhooks, etc.)\n- **Event-driven** architecture\n\n## Quick Start\n\n### Create and Manage Appointments\n\n```typescript\nimport { createManager } from 'reservo';\n\nconst manager = createManager();\n\n// Create\nconst apt = await manager.createAppointment({\n  title: 'Doctor Visit',\n  startsAt: '2024-02-01T14:00:00Z',\n  endsAt: '2024-02-01T14:30:00Z',\n  metadata: { patientId: '12345', email: 'patient@example.com' },\n});\n\n// Confirm\nawait manager.confirmAppointment(apt.id);\n\n// Reschedule\nawait manager.rescheduleAppointment({\n  id: apt.id,\n  startsAt: '2024-02-02T14:00:00Z',\n  endsAt: '2024-02-02T14:30:00Z',\n});\n\n// Cancel\nawait manager.cancelAppointment(apt.id);\n```\n\n### Listen to Events\n\n```typescript\nmanager.on('appointment.created', (event) => {\n  console.log('New appointment:', event.appointment.title);\n});\n\nmanager.on('appointment.confirmed', (event) => {\n  console.log('Confirmed:', event.appointment.id);\n});\n\nmanager.on('appointment.cancelled', (event) => {\n  console.log('Cancelled:', event.appointment.id);\n});\n\nmanager.on('appointment.rescheduled', (event) => {\n  console.log('Rescheduled from:', event.previous?.startsAt);\n  console.log('Rescheduled to:', event.appointment.startsAt);\n});\n```\n\n### Add Email Notifications\n\n```typescript\nimport { createManager } from 'reservo';\nimport { createSMTPTransport } from 'reservo/transports/smtp';\nimport nodemailer from 'nodemailer';\n\nconst transporter = nodemailer.createTransport({\n  host: 'smtp.example.com',\n  port: 587,\n  auth: { user: 'user', pass: 'pass' },\n});\n\nconst manager = createManager();\n\nmanager.use(\n  createSMTPTransport({\n    transporter,\n    from: 'appointments@example.com',\n    template: (event) => ({\n      to: event.appointment.metadata?.email as string,\n      subject: `Appointment ${event.type.split('.')[1]}: ${event.appointment.title}`,\n      text: `Your appointment \"${event.appointment.title}\" scheduled for ${event.appointment.startsAt} has been ${event.type.split('.')[1]}.`,\n    }),\n  })\n);\n```\n\n## API Reference\n\n### `createManager(options?)`\n\nCreate an appointment manager instance.\n\n**Options:**\n- `storage` - Custom storage adapter (default: in-memory)\n- `autoExpire` - Enable automatic expiration checking (default: false)\n- `expireCheckInterval` - Interval for expiration checks in ms (default: 60000)\n\n### Manager Methods\n\n| Method | Description |\n|--------|-------------|\n| `createAppointment(input)` | Create a new appointment |\n| `confirmAppointment(id)` | Confirm an appointment |\n| `cancelAppointment(id)` | Cancel an appointment |\n| `rescheduleAppointment(input)` | Reschedule to new times |\n| `getAppointment(id)` | Get appointment by ID |\n| `listAppointments(filters?)` | List with optional filters |\n| `deleteAppointment(id)` | Delete an appointment |\n| `on(event, handler)` | Register event handler |\n| `off(event, handler)` | Remove event handler |\n| `use(adapter)` | Register transport adapter |\n| `close()` | Clean up resources |\n\n### Appointment Lifecycle\n\n```\ncreated → confirmed → cancelled\n    ↓         ↓\n    ↓     rescheduled → confirmed\n    ↓         ↓\n    └→ expired ←┘\n```\n\n**States:**\n- `created` - Initial state\n- `confirmed` - Appointment confirmed\n- `cancelled` - Appointment cancelled (terminal)\n- `rescheduled` - Times changed, needs re-confirmation\n- `expired` - Past end time (terminal)\n\n### Appointment Object\n\n```typescript\ninterface Appointment {\n  id: string;           // UUID v4\n  title: string;\n  description?: string;\n  startsAt: string;     // ISO 8601 UTC\n  endsAt: string;       // ISO 8601 UTC\n  status: AppointmentStatus;\n  metadata?: Record<string, unknown>;\n  createdAt: string;    // ISO 8601 UTC\n  updatedAt: string;    // ISO 8601 UTC\n}\n```\n\n### Events\n\n| Event | Description |\n|-------|-------------|\n| `appointment.created` | New appointment created |\n| `appointment.confirmed` | Appointment confirmed |\n| `appointment.cancelled` | Appointment cancelled |\n| `appointment.rescheduled` | Appointment times changed |\n| `appointment.expired` | Appointment past end time |\n\n## Custom Storage Adapter\n\nImplement the `StorageAdapter` interface for custom persistence:\n\n```typescript\nimport type { StorageAdapter, Appointment, AppointmentFilters } from 'reservo';\n\nclass PostgresStorage implements StorageAdapter {\n  async create(appointment: Appointment): Promise<Appointment> {\n    // INSERT INTO appointments ...\n  }\n\n  async get(id: string): Promise<Appointment | null> {\n    // SELECT * FROM appointments WHERE id = $1\n  }\n\n  async update(id: string, appointment: Appointment): Promise<Appointment> {\n    // UPDATE appointments SET ... WHERE id = $1\n  }\n\n  async delete(id: string): Promise<boolean> {\n    // DELETE FROM appointments WHERE id = $1\n  }\n\n  async list(filters?: AppointmentFilters): Promise<Appointment[]> {\n    // SELECT * FROM appointments WHERE ...\n  }\n}\n\nconst manager = createManager({ storage: new PostgresStorage() });\n```\n\n## Custom Transport Adapter\n\nImplement the `TransportAdapter` interface for custom notifications:\n\n```typescript\nimport type { TransportAdapter, AppointmentEvent } from 'reservo';\n\nconst webhookTransport: TransportAdapter = {\n  name: 'webhook',\n  events: ['appointment.confirmed', 'appointment.cancelled'],\n\n  async handle(event: AppointmentEvent): Promise<void> {\n    await fetch('https://api.example.com/webhook', {\n      method: 'POST',\n      headers: { 'Content-Type': 'application/json' },\n      body: JSON.stringify(event),\n    });\n  },\n};\n\nmanager.use(webhookTransport);\n```\n\n## Time Handling\n\nAll times are stored and processed in UTC. Input accepts:\n- `Date` objects\n- ISO 8601 strings\n- Unix timestamps (milliseconds)\n\n```typescript\n// All equivalent\nawait manager.createAppointment({\n  title: 'Meeting',\n  startsAt: new Date('2024-01-15T10:00:00Z'),\n  endsAt: new Date('2024-01-15T11:00:00Z'),\n});\n\nawait manager.createAppointment({\n  title: 'Meeting',\n  startsAt: '2024-01-15T10:00:00Z',\n  endsAt: '2024-01-15T11:00:00Z',\n});\n\nawait manager.createAppointment({\n  title: 'Meeting',\n  startsAt: 1705316400000,\n  endsAt: 1705320000000,\n});\n```\n\n## License\n\nMIT\n","readmeFilename":"README.md","_rev":"1-a82b9252430bf1a205fc8dd432014df0"}