npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@oddle.me/oe-dining-pref

v0.12.5

Published

A compilation of util functions for OE discovery flow.

Downloads

197

Readme

@oddle.me/oe-dining-pref

A compilation of util functions for OE discovery flow.

Installation

npm install --save @oddle.me/oe-dining-pref

Initialize

This should go at the top of your application

import { initConfig } from '@oddle.me/oe-dining-pref'

initConfig({
  isProduction: isProduction(), // boolean, required
  country: 'SG', // ISO 3166-1 A2
})

requiredConfig

{
  isProduction: false
}

optionalConfig

{
  omsApi: 'https://eats.oddle.me/proxy-api/oddle-canary.oddle.me/api',
  typesenseNodes: [
    'https://jrod6csnbp2aye57p-1.a1.typesense.net',
  ],
  typesenseOpts: {} // https://typesense.org/docs/0.20.0/api/authentication.html#search-delivery-network
}

Usage

getDineinMenuTickets

this function is a combination of getDineinOutletTickets, getAllMenus, sortMenus
returns a list of populated menus with tickets for each store/outlet in addresses

import moment from 'moment'
import { getDineinMenuTickets } from '@oddle.me/oe-dining-pref'

getDineinMenuTickets({
  dineinDateTime: moment().add(1, 'day').format('YYYYMMDD HHmm'),
  numPax,
  menuTagNames,
  menuSortType,
}).then(console.log)

getDineinMenuTickets({
  dineinDateTime: undefined, // set to undefined to list tickets of all dine-in menus (no timeslots will be returned)
  numPax,
  menuTagNames,
  menuSortType,
}).then(console.log)

/*
  sort order:
    - menus: sorted by `menuSortType`
    - addresses/stores: sorted by relevancy of tickets' timeslots
    - tickets: sorted by timeslots that are closest to search time, then sorted by `ticketIsFeatured`
    - timeslots: sorted from earliest to latest

  // response
  [{
    ...menu,
    _totalMatchingTickets, // number -> experiences with timeslots near dineinDateTime
    _totalNonMatchingTickets, // number -> X experiences on other dates
    addresses: [{
      // if a menu has no `addresses` -> that menu wont be returned
      ...addr,
      _numMatchingTickets, // number -> experiences with timeslots near dineinDateTime
      _numNonMatchingTickets, // number -> X experiences on other dates
      tickets: [{
        // if `dineinDateTime` is specified -> first ticket in array is guaranteed to have best matching timeslot
        // if an address has no `tickets` -> that address wont be returned
        ...ticket,
        ticketPaymentType, // NO_PAYMENT | DEPOSIT | FULL_PAYMENT
        ticketPriceType, // PER_PAX | PER_BOOKING
        ticketPrice, // if `ticketUsualPrice` has value -> `ticketPrice` becomes discounted price
        ticketUsualPrice, // if `ticketUsualPrice` has value -> `ticketPrice` becomes discounted price
        numRecurringServices, // see "special date availability" in https://oddle-pm.atlassian.net/l/c/PfeS2U0G
        numNonRecurringServices, // see "special date availability" in https://oddle-pm.atlassian.net/l/c/PfeS2U0G
        specialDates, // see "special date availability" in https://oddle-pm.atlassian.net/l/c/PfeS2U0G
        specialDatesContinuous, // to determine whether `specialDates` are continuous or not
        ticketIsFeatured, // true | false
        restaurantPolicy, // string | null
        restaurantPolicyDefault, // string | null -> system generated policy
        cancellationPolicy, // string | null
        cancellationPolicyDefault, // string | null -> system generated policy
        minPax, // number | null
        maxPax, // number | null
        areas, // bookable areas of a ticket
        areasDisplayName, // string -> concatenated display names of all areas
        timeslots: [{ // timeslots will be empty if `dineinDateTime` is not specified
          slot, // HHmm format
          _isExactMatch, // true | false
          _isClosestMatch, // true | false
        }, ...timeslots], // number of timeslots returned depends on `numTimeslotsLookaround` and `dineinTimeLookaround`
        _hasMatchingTs, // true | false -> tickets with _hasMatchingTs === false will be shown on "X experiences on other dates" popup
      }, ...tickets]
    }, ...addresses],
  }, ...menus]
*/

getDiscoveryMenus

this function is a combination of getMenuDistances, getAllMenuTimeSlots, getAllMenus, sortMenus
returns a list of populated menus with distance, time options info
sorted based on user address/timeslot and sortType selection

import { getDiscoveryMenus } from '@oddle.me/oe-dining-pref'

getDiscoveryMenus({
  menuIds, // undefined || [...menuIds]
  timeSlot: '0800-1000', // HHmm-HHmm or HHmm (string | null)
  deliveryDate: '20210613', // YYYYMMDD (string | null)
  pickupOrDelivery: 'delivery', // 'pickup' || 'delivery'
  coords: '-48.9044488,-71.015625',
  sortType: 'recommended', // null || 'recommended' || 'distance' || 'deliveryFee' || 'minimumOrder' || 'newlyListed'
  tagNames, // undefined || null || ['Western', 'Japanese', ...]
  excludeMenusWithUnavailableTS, // undefined || true (default) || false
  excludeMenusWithUnavailableStore, // undefined || true (default) || false
}).then(console.log)

getMenuDistances

import { getMenuDistances } from '@oddle.me/oe-dining-pref'

getMenuDistances('-48.9044488,-71.015625').then(console.log)

getAllMenuTimeSlots

import { getAllMenuTimeSlots } from '@oddle.me/oe-dining-pref'

getAllMenuTimeSlots({
  menuIds, // undefined || [...menuIds]
  timeSlot: '0800-1000', // HHmm-HHmm or HHmm (string | null)
  deliveryDate: '20210613', // YYYYMMDD (string | null)
  pickupOrDelivery: 'delivery', // 'pickup' || 'delivery'
}).then(console.log)

getAllMenus

use this function to populate menus returned from getMenuDistances and getAllMenuTimeSlots

import { getAllMenus } from '@oddle.me/oe-dining-pref'

getAllMenus({
  menuIds, // optional, set to filter by menuId
  fields: [...fields], // optional, set to null to fetch all fields (very slow)
  tagNames: [...tagNames], // optional: undefined || null || ['Western', 'Japanese', ...]
}).then(console.log)

getMenuDiningServices

use this function to get info about delivery/pickup/reservation services of a menuId

import { getMenuDiningServices } from '@oddle.me/oe-dining-pref'

getMenuDiningServices('2c9f81405e515cf8015e571c3c6e00b8').then(console.log)

sortMenus

use this function to sort menus returned from getMenuDistances and getAllMenuTimeSlots (populated with getAllMenus)

import { sortMenus } from '@oddle.me/oe-dining-pref'

const sortedMenus = sortMenus(menus, {
  pickupOrDelivery: 'delivery', // null || 'pickup' || 'delivery'
  sortType: 'recommended', // null || 'recommended' || 'distance' || 'deliveryFee' || 'minimumOrder' || 'newlyListed'
  timeSelected: true, // user selected preferred timeslot or not
  addrSelected: true, // user selected preferred address or not
})

getSortFunctions, multiSort

use getSortFunctions to get sort functions order (sort priority) if you want to implement your own compare functions (instead of using sortMenus) or customize the sort priorities

import { multiSort, getSortFunctions } from '@oddle.me/oe-dining-pref'

const { sortFns, mapMenu } = getSortFunctions({
  pickupOrDelivery: 'delivery', // 'pickup' || 'delivery'
  sortType: 'recommended', // 'recommended' || 'distance' || 'deliveryFee' || 'minimumOrder' || 'newlyListed'
  timeSelected: true, // user selected preferred timeslot or not
  addrSelected: true, // user selected preferred address or not
})

const customSortFn = (a, b) => a - b

const sortedMenus = multiSort(menus.map(mapMenu), [
  customSortFn,
  ...sortFns.map(it => it.compareFn),
])