@everytravel/shared

v1.0.19

Published

A comprehensive shared package for Everytravel containing Mongoose models and CRUD operations for hotel booking, user management, and transaction handling. Updated with improved model syntax and enhanced error handling.

Downloads

80

Readme

@everytravel/shared

A comprehensive shared package for Everytravel containing Mongoose models and CRUD operations for hotel booking, user management, and transaction handling. Includes OAuth authentication support for Google, Facebook, and Apple Sign-In.

šŸ“¦ Package Structure

shared/
ā”œā”€ā”€ models/           # All Mongoose models
│   ā”œā”€ā”€ User.model.js
│   ā”œā”€ā”€ Host.model.js
│   ā”œā”€ā”€ Property.model.js
│   ā”œā”€ā”€ Room.model.js
│   ā”œā”€ā”€ Deal.model.js
│   ā”œā”€ā”€ Booking.model.js
│   ā”œā”€ā”€ Review.model.js
│   ā”œā”€ā”€ Transaction.model.js
│   ā”œā”€ā”€ Card.model.js
│   ā”œā”€ā”€ Discount.model.js
│   ā”œā”€ā”€ Wallet.mode.js
│   └── index.js
ā”œā”€ā”€ create/           # Create operations
│   └── index.js
ā”œā”€ā”€ read/             # Read operations
│   └── index.js
ā”œā”€ā”€ update/           # Update operations
│   └── index.js
ā”œā”€ā”€ delete/           # Delete operations
│   └── index.js
ā”œā”€ā”€ methods/          # Main methods index
│   └── index.js
ā”œā”€ā”€ index.js          # Main package entry point
ā”œā”€ā”€ package.json
└── README.md

šŸš€ Installation

npm install @everytravel/shared

šŸ“‹ Dependencies

  • mongoose: ^8.0.3

šŸ”§ Usage

Import Options

1. Import Everything

import * as Shared from '@everytravel/shared';

2. Import Specific CRUD Operations

import { createOne } from '@everytravel/shared/create';
import { getMany, getOne } from '@everytravel/shared/read';
import { updateOne } from '@everytravel/shared/update';
import { deleteOne } from '@everytravel/shared/delete';

3. Import Models

import { User, Property, Booking, Suite } from '@everytravel/shared/models';

4. Import All Methods (Backward Compatible)

import { createOne, getMany, getOne, updateOne, deleteOne } from '@everytravel/shared/methods';

šŸ—„ļø Models

User Model

const userData = {
  firstName: "John",
  lastName: "Doe",
  email: "[email protected]",
  phoneNumber: {
    countryCode: "+1",
    number: "5551234567"
  },
  password: "hashedPassword",
  dateOfBirth: new Date("1990-01-01"),
  gender: "male",
  verifiedEmail: true,
  country: "USA",
  address: "123 Main St",
  profilePicUrl: "https://example.com/avatar.jpg",
  // OAuth provider IDs (optional)
  googleId: "google_oauth_id",
  facebookId: "facebook_oauth_id", 
  appleId: "apple_oauth_id"
};

Host Model

const hostData = {
  firstName: "Jane",
  lastName: "Smith", 
  email: "[email protected]",
  phoneNumber: {
    countryCode: "+1",
    number: "5559876543"
  },
  password: "hashedPassword",
  dateOfBirth: new Date("1985-05-15"),
  gender: "female",
  verifiedEmail: true,
  country: "USA",
  address: "789 Business Ave",
  profilePicUrl: "https://example.com/host-avatar.jpg",
  // OAuth provider IDs (optional)
  googleId: "google_oauth_id",
  facebookId: "facebook_oauth_id",
  appleId: "apple_oauth_id"
};

Property Model

const propertyData = {
  name: "Luxury Hotel",
  type: "Hotel", // Hotel, Apartment, Guesthouse, Villa, Resort
  description: "A luxurious 5-star hotel",
  location: {
    address: "456 Luxury Ave",
    city: "New York",
    country: "USA",
    zipCode: "10001",
    coordinates: {
      lat: 40.7128,
      lng: -74.0060
    }
  },
  metaTags: ["luxury", "business"],
  facilities: ["wifi", "pool", "spa"],
  starRating: 5,
  owner: hostId
};

Room Model

const roomData = {
  property: propertyId,
  roomName: "Deluxe Room",
  pricePerNight: 200,
  priceCurrency: "USD",
  status: "active", // active, inactive
  sizeSqMeters: 30,
  numBeds: 1,
  bedType: "king",
  quantity: 5,
  roomLeft: 3,
  maxGuests: 2,
  stars: 4,
  rating: 4.5,
  details: {
    description: "Spacious room with city view",
    amenities: {
      comfort: ["air conditioning", "minibar"],
      internet: ["free wifi"],
      bathroom: ["private bathroom", "bathtub"]
    }
  },
  refundPolicy: {
    zero: { refundPercentage: 0 },
    partial: { refundPercentage: 75 },
    full: { refundPercentage: 100 }
  },
  show: true,
  softDeleted: false
};

Deal Model

const dealData = {
  dealName: "Summer Special 2024",
  discount: 25, // 0-100 percentage
  fromDate: new Date("2024-06-01"),
  toDate: new Date("2024-08-31"),
  eligibleRoomIds: [roomId1, roomId2],
  eligibleRooms: ["Deluxe Room", "Suite"], // Populated from room names
  guestTargeting: "all guests", // all guests, logged-in users only, corporate users, repeat guests
  status: "upcoming", // active, paused, ended, upcoming, completed
  host: hostId,
  isPaused: false,
  isEnded: false,
  validityPeriod: "2024-06-01 - 2024-08-31" // Auto-generated from dates
};

Booking Model

const bookingData = {
  user: userId,
  suite: suiteId,
  property: propertyId,
  checkInDate: new Date("2024-01-15"),
  checkOutDate: new Date("2024-01-18"),
  guests: {
    adults: 2,
    children: 1
  },
  numRooms: 1,
  price: {
    base: 600,
    taxes: 60,
    discounts: 30,
    total: 630,
    currency: "USD"
  },
  paymentStatus: "paid", // pending, paid, failed, refunded
  bookingStatus: "confirmed" // confirmed, cancelled, completed
};

šŸ”„ CRUD Operations

Create Operations

createOne(Model, data)

Creates a new document in the specified model.

import { createOne } from '@everytravel/shared/create';
import { User } from '@everytravel/shared/models';

// Create a new user
const newUser = await createOne(User, userData);
console.log('Created user:', newUser);

Read Operations

getMany(Model, filter, options)

Retrieves multiple documents with optional filtering and pagination.

import { getMany } from '@everytravel/shared/read';
import { Property } from '@everytravel/shared/models';

// Get all properties
const allProperties = await getMany(Property);

// Get properties with filters
const luxuryHotels = await getMany(Property, {
  type: "Hotel",
  starRating: { $gte: 4 }
}, {
  sort: { starRating: -1 },
  limit: 10,
  skip: 0,
  populate: "owner"
});

getOne(Model, filter, options)

Retrieves a single document.

import { getOne } from '@everytravel/shared/read';
import { User } from '@everytravel/shared/models';

// Get user by email
const user = await getOne(User, { email: "[email protected]" }, {
  populate: "wallet"
});

Update Operations

updateOne(Model, filter, update, options)

Updates a single document.

import { updateOne } from '@everytravel/shared/update';
import { User } from '@everytravel/shared/models';

// Update user profile
const updatedUser = await updateOne(
  User,
  { _id: userId },
  { 
    firstName: "Johnny",
    verifiedEmail: true 
  },
  { new: true }
);

Delete Operations

deleteOne(Model, filter)

Deletes a single document.

import { deleteOne } from '@everytravel/shared/delete';
import { Booking } from '@everytravel/shared/models';

// Delete a booking
const deletedBooking = await deleteOne(Booking, { _id: bookingId });

šŸ“Š Complete Example

import { 
  createOne, 
  getMany, 
  getOne, 
  updateOne, 
  deleteOne 
} from '@everytravel/shared/methods';
import { 
  User, 
  Host,
  Property, 
  Room,
  Deal,
  Booking 
} from '@everytravel/shared/models';

// Create a host with OAuth support
const host = await createOne(Host, {
  firstName: "Jane",
  lastName: "Smith",
  email: "[email protected]",
  password: "hashedPassword",
  verifiedEmail: true,
  // OAuth fields (optional)
  googleId: "google_oauth_id",
  facebookId: "facebook_oauth_id"
});

// Create a property
const property = await createOne(Property, {
  name: "Sunset Resort",
  type: "Resort",
  owner: host._id,
  starRating: 5
});

// Create a room
const room = await createOne(Room, {
  property: property._id,
  roomName: "Ocean View Suite",
  pricePerNight: 300,
  priceCurrency: "USD",
  maxGuests: 2,
  sizeSqMeters: 50
});

// Create a deal
const deal = await createOne(Deal, {
  dealName: "Summer Special",
  discount: 20,
  fromDate: new Date("2024-06-01"),
  toDate: new Date("2024-08-31"),
  eligibleRoomIds: [room._id],
  guestTargeting: "all guests",
  host: host._id
});

// Create a user with OAuth support
const user = await createOne(User, {
  firstName: "John",
  lastName: "Doe",
  email: "[email protected]",
  verifiedEmail: true,
  // OAuth fields (optional)
  googleId: "google_oauth_id",
  appleId: "apple_oauth_id"
});

// Create a booking
const booking = await createOne(Booking, {
  user: user._id,
  room: room._id,
  property: property._id,
  checkInDate: new Date("2024-02-01"),
  checkOutDate: new Date("2024-02-05"),
  guests: { adults: 2, children: 0 },
  price: { base: 1200, taxes: 120, total: 1320, currency: "USD" }
});

// Get all bookings for a user
const userBookings = await getMany(Booking, 
  { user: user._id },
  { populate: ["room", "property"] }
);

// Get all deals for a host
const hostDeals = await getMany(Deal, 
  { host: host._id },
  { populate: "eligibleRoomIds" }
);

// Update booking status
await updateOne(Booking, 
  { _id: booking._id },
  { bookingStatus: "completed" }
);

// Find user by OAuth provider ID
const googleUser = await getOne(User, { googleId: "google_oauth_id" });

šŸ”— Model Relationships

User Relationships

  • Wallet: One-to-one relationship
  • Saved Items: Arrays of references (Bookings, Rides, Suites)
  • Cards: Array of Card references
  • Transactions: Array of Transaction references
  • Offers: Array of Discount references
  • OAuth Providers: Google, Facebook, Apple authentication IDs

Host Relationships

  • Properties Created: Array of Property references
  • OAuth Providers: Google, Facebook, Apple authentication IDs

Property Relationships

  • Owner: Reference to Host
  • Rooms: Array of Room references

Room Relationships

  • Property: Reference to Property
  • Reviews: Array of Review references
  • Deals: Referenced by Deal eligibleRoomIds

Deal Relationships

  • Host: Reference to Host who created the deal
  • Eligible Rooms: Array of Room references via eligibleRoomIds

Booking Relationships

  • User: Reference to User
  • Suite: Reference to Suite
  • Property: Reference to Property
  • Discount Used: Reference to Discount

šŸ› ļø Error Handling

All CRUD operations include comprehensive error handling:

try {
  const result = await createOne(User, userData);
} catch (error) {
  console.error('Error creating user:', error.message);
  // Handle specific error cases
}

šŸ“¦ Package Exports

The package provides the following exports:

{
  "exports": {
    "./models": "./models/index.js",
    "./methods": "./methods/index.js",
    "./create": "./create/index.js",
    "./read": "./read/index.js",
    "./update": "./update/index.js",
    "./delete": "./delete/index.js"
  }
}

šŸ” OAuth Authentication Support

This package includes OAuth provider ID fields for seamless integration with authentication systems:

Supported OAuth Providers

  • Google OAuth 2.0: googleId field
  • Facebook OAuth: facebookId field
  • Apple Sign-In: appleId field

OAuth Integration Example

// Find user by OAuth provider ID
const user = await getOne(User, { googleId: "google_oauth_id" });

// Update user with OAuth information
await updateOne(User, 
  { email: "[email protected]" },
  { 
    googleId: "new_google_id",
    verifiedEmail: true,
    profilePicUrl: "https://example.com/avatar.jpg"
  }
);

// Check if user exists with any OAuth provider
const existingUser = await getOne(User, {
  $or: [
    { googleId: "google_id" },
    { facebookId: "facebook_id" },
    { appleId: "apple_id" }
  ]
});

šŸ¤ Contributing

  1. Follow the modular structure
  2. Add comprehensive JSDoc comments
  3. Include error handling in all operations
  4. Maintain backward compatibility
  5. Update this README for any new features
  6. Test OAuth integration scenarios

šŸ“„ License

ISC License

šŸ”— Related Packages

  • @everytravel/server-primera - Backend server implementation with Passport.js OAuth
  • @everytravel/client - Frontend client application

šŸ”„ Version History

v1.0.9 (Latest)

  • āœ… Fixed Deal model validation issue with validityPeriod field
  • āœ… Added Room and Deal model documentation
  • āœ… Enhanced error handling in deal controllers
  • āœ… Code cleanup and production-ready optimizations
  • āœ… Updated model relationships and examples

v1.0.8

  • āœ… Booking filter enhancements with type and status filters
  • āœ… Enhanced API consistency across user and host endpoints

v1.0.7

  • āœ… Property & Suite management enhancements
  • āœ… Added bulk operations and soft delete functionality
  • āœ… Enhanced indexes and performance optimizations

v1.0.3

  • āœ… Added OAuth provider ID fields to User and Host models
  • āœ… Support for Google, Facebook, and Apple Sign-In
  • āœ… Backward compatible with existing data
  • āœ… Enhanced documentation with OAuth examples

v1.0.2

  • āœ… Initial OAuth field additions
  • āœ… Database schema updates

v1.0.1

  • āœ… Core CRUD operations
  • āœ… Basic model structure

Note: This package is designed to be used with MongoDB and Mongoose. Ensure your MongoDB connection is properly configured before using these models and operations. The OAuth fields are optional and backward compatible.

Deal Model Note: The validityPeriod field is automatically generated from fromDate and toDate fields. When creating deals programmatically, ensure both date fields are provided for proper validation.