Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
Size: Mime:
const fixture = require('./fixture')
const CompositionLayer = require('./schema')

// @TODO either
// 1. reverse() to undo all coercsions SOMEHOW
// 2. find a more ingenius solution
// 3. have the view send the data the proper format,
//    and we add a mapping for UPDATES not just FETCHING

// @TODO coerce property names toLowerCase
// .scope('namespace')
// or Type.string.url.image('default url')
// .name('product')

// @TODO 1 could even do .namespace('product'), to auto register types, not needed though
// @TODO 2 could use namespaces to create conditions that allow different defaults
//      for those names for easy centralization of entity defaults
//      for now can just call it with an argument if it needs a default
// Type.register('Nav').enum('identifier', 'moose', 'eh').default('identifier')
//
// @TODO am unsure about this one
// Composition.props(['image'])
// 'children.products': [PRODUCT],
// pricing: Composition.pipe(indexBy('label'), PRICE),

// const CompositionLayer = { Type, Schema, Composition, Transform }

const { Type, Schema, Composition, Transform } = CompositionLayer
const { indexBy } = Transform

// ---- reusable root registrations ----

/**
 * define an image with a default for this scope
 */
const TypeImage = Type.image('default url')

/**
 * coerce all images
 */
Type.registerProperty('*.image', TypeImage)

/**
 * coerce all identifiers
 */
Type.registerProperty('*.identifier', Type.id())

/**
 * make a type
 */
Type.register('Nav').enum('identifier', 'moose', 'eh').default('identifier')

// ---- domain Compositions ----

/**
 * our product schema
 */
const PRODUCT = Composition.schema({
  name: String,
})

/**
 * @NOTE this could use `transform('pricing.prices', indexBy('label'))`
 *       but better to do less transforming,
 *       and more entity composition with related pieces,
 *       future-friendly for only selecting properties required
 *       @example graphql, where we'd get currencycode as-needed
 *
 *
 * @example input
 *   {
 *     pricing: {
 *       currencycode: '$',
 *       prices: [
 *         { label: 'sale', type: 'Sale', value: '40.0' },
 *         { label: 'reg', type: 'Reg', value: '$274.40' },
 *       ],
 *     },
 *   }
 *
 * @see above for Money entity
 * @example output
 * {pricing: Money}
 *
 */
const PRICING = Type.Moneys()

/**
 * our catalog schema
 */
const CATALOG = Composition
  /**
   * @name transform/reshape/evolve
   *
   * 1. skus becomes an object with `.identifier` as the index
   * 2. pricing uses `label` as the index
   *
   * @example input
   *  {
   *    skus: [
   *      {
   *        identifier: 'id',
   *        name: 'eh'
   *      }
   *    ],
   *    {
   *      pricing: {
   *        prices: [
   *          { label: 'sale', type: 'Sale', value: '40.0' },
   *        ]
   *      }
   *    }
   *  }
   *
   * @example output
   *  {
   *    skus: { 'id': {name: 'eh'} },
   *    pricing: Money
   *  }
   *
   *
   *
   */
  .reshape({
    skus: indexBy('identifier'),
    pricing: PRICING,
  })
  // --- catalog continued

  /**
   * our api response
   * has a lot of objects
   * that just have 1 property in an object
   *
   * this lets us easily
   * lift every `.children` property up
   *
   * @NOTE defaults 1 level lifting, can pass in a number to move it higher
   */
  .lift('children')
  .schema({
    /**
     * @NOTE this would be optional,
     *       because we registered all .image, before
     *       and we can log our schema with .toJSON
     */
    image: TypeImage,
    navtype: Type.Nav(),

    /**
     * we already lifted .children, so instead of children.products
     */
    products: [PRODUCT],
  })