/**
 * ```typescript
 * import { MacroGetter } from 'macro-decorators';
 * ```
 *
 * A getter for a macro.
 */ export type MacroGetter = param obj param key returns ( obj : any , key : string | symbol ) => any ; /**
 * ```typescript
 * import { MacroSetter } from 'macro-decorators';
 * ```
 *
 * A setter for a macro.
 */ export type MacroSetter = param obj param key param value ( obj : any , key : string | symbol , value : any ) => void ; /**
 * ```typescript
 * import { MacroDescriptor } from 'macro-decorators';
 * ```
 *
 * A descriptor for a macro. Contains either a macro getter, a macro setter, or
 * both.
 */ export type MacroDescriptor = { get ? : MacroGetter ; set ? : MacroSetter ; } ; fullNameMacro fullNameMacro fullNameMacro param definition export default function macro ( definition ) { let getter ; let setter ; if ( typeof definition === 'function' ) { getter = definition ; } else { getter = definition . get ; setter = definition . set ; } return function ( _target , key ) { let desc = { } ; if ( getter !== undefined ) { desc . get = function ( ) { return getter ! . call ( this , this , key ) ; } ; } if ( setter !== undefined ) { desc . set = function ( value ) { return setter ! . call ( this , this , key , value ) ; } ; } return desc ; } ; } function getPath ( obj , path ) { let segments = path . split ( '.' ) ; let current = obj ; for ( let segment of segments ) { if ( current === undefined || current === null ) { break ; } current = typeof current . get === 'function' ? current . get ( segment ) : current [ segment ] ; } return current ; } function getPaths ( obj , paths ) { return paths . map ( p => getPath ( obj , p ) ) ; } function setPath ( obj , path , value ) { let objPath = path . substr ( 0 , path . lastIndexOf ( '.' ) ) ; let key = path . substr ( path . lastIndexOf ( '.' ) + 1 ) ; let resolvedObj = objPath ? getPath ( obj , objPath ) : obj ; if ( typeof resolvedObj . set === 'function' ) { resolvedObj . set ( key , value ) ; } else { resolvedObj [ key ] = value ; } } alias alias param path export function alias ( path ) { return macro ( { get ( obj ) { return getPath ( obj , path ) ; } , set ( obj , _key , value ) { setPath ( obj , path , value ) ; } , } ) ; } deprecatingAlias param path param message export function deprecatingAlias ( path , message ) { return macro ( { get ( obj , key ) { console . warn ( `You got ${ obj }#${ String ( key ) }, but that value has been deprecated: ${ message }` ) ; return getPath ( obj , path ) ; } , set ( obj , key , value ) { console . warn ( `You set ${ obj }#${ String ( key ) }, but that value has been deprecated: ${ message }` ) ; setPath ( obj , path , value ) ; } , } ) ; } reads reads reads param path param defaultValue export function reads ( path , defaultValue ? ) { return macro ( obj => { let value = getPath ( obj , path ) ; if ( value === null || value === undefined ) { value = typeof defaultValue === 'function' ? defaultValue ( ) : defaultValue ; } return value ; } ) ; } overridableReads param path export function overridableReads ( path ) { return macro ( { get ( obj ) { return getPath ( obj , path ) ; } , set ( obj , key , value ) { Object . defineProperty ( obj , key , { writable : true , configurable : true , value , } ) ; } , } ) ; } function isEmpty ( value ) { if ( ! Boolean ( value ) ) { return true ; } else if ( Array . isArray ( value ) && value . length === 0 ) { return true ; } return false ; } and param paths export function and ( ... paths ) { return macro ( obj => getPaths ( obj , paths ) . reduce ( ( a , b ) => a && b , true ) ) ; } bool param path export function bool ( path ) { return macro ( obj => Boolean ( getPath ( obj , path ) ) ) ; } empty param path export function empty ( path ) { return macro ( obj => isEmpty ( getPath ( obj , path ) ) ) ; } equal param path param value export function equal ( path , value ) { return macro ( obj => getPath ( obj , path ) === value ) ; } gt param path param value export function gt ( path , value ) { return macro ( obj => getPath ( obj , path ) > value ) ; } gte param path param value export function gte ( path , value ) { return macro ( obj => getPath ( obj , path ) >= value ) ; } not param path export function not ( path ) { return macro ( obj => ! getPath ( obj , path ) ) ; } notEmpty param path export function notEmpty ( path ) { return macro ( obj => ! isEmpty ( getPath ( obj , path ) ) ) ; } match param path param value export function match ( path , regex ) { return macro ( obj => regex . test ( getPath ( obj , path ) ) ) ; } param path export function nullish ( path ) { return macro ( obj => { let value = getPath ( obj , path ) ; return value === null || value === undefined ; } ) ; } or param path export function or ( ... paths ) { return macro ( obj => getPaths ( obj , paths ) . reduce ( ( a , b ) => a || b , false ) ) ; } lt param path param value export function lt ( path , value ) { return macro ( obj => getPath ( obj , path ) < value ) ; } lte param path param value export function lte ( path , value ) { return macro ( obj => getPath ( obj , path ) <= value ) ; } function setFrom ( arr ) { let set = new Set ( ) ; arr . forEach ( v => set . add ( v ) ) ; return set ; } function getValues ( set ) { if ( set . values ) { return Array . from ( set ) ; } let values = [ ] ; set . forEach ( v => values . push ( v ) ) ; return values ; } collect param paths export function collect ( ... paths ) { return macro ( obj => getPaths ( obj , paths ) ) ; } diff param paths export function diff ( ... paths ) { return macro ( obj => { let arrays = getPaths ( obj , paths ) ; let intersect = arrays . shift ( ) ; for ( let arr of arrays ) { let values = setFrom ( arr ) ; intersect = intersect . filter ( ( v ) => ! values . has ( v ) ) ; } return intersect ; } ) ; } filter param path param fn export function filter ( path , fn ) { return macro ( obj => getPath ( obj , path ) . filter ( fn ) ) ; } filterBy filterBy param path param key param value export function filterBy ( path , key , value ? ) { if ( value !== undefined ) { return filter ( path , ( v ) => v [ key ] === value ) ; } else { return filter ( path , ( v ) => Boolean ( v [ key ] ) ) ; } } intersect param paths export function intersect ( ... paths ) { return macro ( obj => { let arrays = getPaths ( obj , paths ) ; let intersect = arrays . shift ( ) ; for ( let arr of arrays ) { let values = setFrom ( arr ) ; intersect = intersect . filter ( ( v ) => values . has ( v ) ) ; } return intersect ; } ) ; } map param path param fn export function map ( path , fn ) { return macro ( obj => getPath ( obj , path ) . map ( fn ) ) ; } mapBy param path param key export function mapBy ( path , key ) { return map ( path , v => v [ key ] ) ; } max param path export function max ( path ) { return macro ( obj => Math . max ( ... getPath ( obj , path ) ) ) ; } max param path export function min ( path ) { return macro ( obj => Math . min ( ... getPath ( obj , path ) ) ) ; } sort param path param fn export function sort ( path , fn ) { return macro ( obj => getPath ( obj , path ) . slice ( ) . sort ( fn ) ) ; } sortBy param path param key param asc export function sortBy ( path , key , asc = true ) { return sort ( path , ( a , b ) => { if ( a [ key ] < b [ key ] ) { return asc ? - 1 : 1 ; } else if ( a [ key ] > b [ key ] ) { return asc ? 1 : - 1 ; } return 0 ; } ) ; } sum param path export function sum ( path ) { return macro ( obj => getPath ( obj , path ) . reduce ( ( s , v ) => s + v , 0 ) ) ; } union param paths export function union ( ... paths ) { return macro ( obj => { let arrays = getPaths ( obj , paths ) ; let union = new Set ( ) ; for ( let arr of arrays ) { arr . forEach ( ( v ) => union . add ( v ) ) ; } return getValues ( union ) ; } ) ; } unique param path export function unique ( path ) { return union ( path ) ; } uniqueBy param path param key export function uniqueBy ( path , key ) { return macro ( obj => { let arr = getPath ( obj , path ) ; let union = new Set ( ) ; let values = [ ] ; arr . forEach ( ( v ) => { let keyValue = v [ key ] ; if ( ! union . has ( keyValue ) ) { union . add ( keyValue ) ; values . push ( v ) ; } } ) ; return values ; } ) ; }