module import { structEq , setKey , conservatively , findIndex , Option , DEV_ENV , warning } from './../utils' ; import { Lens , Prism } from './base' ; export type PropExpr < O , P > = ( x : O ) => P ; const PROP_EXPR_RE = new RegExp ( [ '^' , 'function' , '\\(' , '[^), ]+' , '\\)' , '\\{' , '("use strict";)?' , 'return\\s' , '[^\\.]+\\.(\\S+?);?' , '\\}' , '$' ] . join ( '\\s*' ) ) ; const WALLABY_PROP_EXPR_RE = new RegExp ( [ '^' , 'function' , '\\(' , '[^), ]+' , '\\)' , '\\{' , '("use strict";)?' , '(\\$_\\$wf\\(\\d+\\);)?' , 'return\\s' , '(\\$_\\$w\\(\\d+, \\d+\\),\\s)?' , '[^\\.]+\\.(\\S+?);?' , '\\}' , '$' ] . join ( '\\s*' ) ) ; export function parsePropertyPath ( getterSource ) { const exprRegexp = process . env . NODE_ENV === 'wallaby' ? WALLABY_PROP_EXPR_RE : PROP_EXPR_RE ; const exprRegexpGroup = process . env . NODE_ENV === 'wallaby' ? 4 : 2 ; const parse = getterSource . match ( exprRegexp ) ; if ( parse && parse [ exprRegexpGroup ] ) { return parse [ exprRegexpGroup ] . split ( '.' ) ; } else { throw new TypeError ( `Expected a property expression, got "${ getterSource }".

      A property expression should be a referentially transparent (no side-effects),
      single-expression "getter" function.

      Correct example: "function (x) { return x.some }" or "x => x.some".
      Incorrect example: "function (x) { var y = x.some; return y }" or "({some}) => some"` ) ; } } /**
 * Extract a list of property names from a  PropExpr param target example returns throws export function extractPropertyPath < TObject , TProperty > ( target ) { return parsePropertyPath ( target . toString ( ) ) ; } export interface KeyImplFor < TObject > { example < K extends keyof TObject > ( k ) : Lens < TObject , TObject [ K ] > ; } param k export function keyImpl < TValue = any > ( k ) ; example template TObject export function keyImpl < TObject = any > ( ) ; export function keyImpl < TObject > ( k ? ) { return k === undefined ? < K extends keyof TObject > ( k ) : Lens < TObject , TObject [ K ] > => Lens . create < TObject , TObject [ K ] > ( ( s ) => s [ k ] , ( v , s ) => setKey ( k , v , s ) ) : Lens . create ( ( s ) => s [ k ] as Option < any > , ( v , s ) => setKey ( k , v , s ) ) ; } let propExprDeprecatedWarnings = 0 ; function warnPropExprDeprecated ( path ) { if ( propExprDeprecatedWarnings < 10 ) { propExprDeprecatedWarnings ++ ; const propExpr = `x.${ path . join ( '.' ) }` ; const keys = `'${ path . join ( "', '" ) }'` ; warning ( `The property expression overload of Atom.lens and Lens.prop are deprecated and ` + `will be removed in next versions of Focal. Please use the key name overload for ` + `Atom.lens and Lens.key instead. ` + `You can convert your code by changing the calls:
  a.lens(x => ${ propExpr }) to a.lens(${ keys }),
  Lens.prop((x: T) => ${ propExpr }) to Lens.key<T>()(${ keys }).` ) ; } } export function propImpl < TObject , TProperty > ( getter ) { const path = extractPropertyPath ( getter as PropExpr < TObject , TProperty > ) ; if ( DEV_ENV ) warnPropExprDeprecated ( path ) ; return Lens . compose < TObject , TProperty > ( ... path . map ( keyImpl ( ) ) ) ; } export function indexImpl < TItem > ( i ) { if ( i < 0 ) throw new TypeError ( `${ i } is not a valid array index, expected >= 0` ) ; return Prism . create ( ( xs ) => xs [ i ] as Option < TItem > , ( v , xs ) => { if ( xs . length <= i ) { return xs . concat ( Array ( i - xs . length ) , [ v ] ) ; } else if ( structEq ( v , xs [ i ] ) ) { return xs ; } else { return xs . slice ( 0 , i ) . concat ( [ v ] , xs . slice ( i + 1 ) ) ; } } ) ; } export function withDefaultImpl < T > ( defaultValue ) { return Lens . replace ( undefined , defaultValue ) as Lens < Option < T > , T > ; } function choose < T , U > ( getLens ) { return Lens . create ( ( s ) => getLens ( s ) . get ( s ) , ( v , s ) => getLens ( s ) . set ( v , s ) ) ; } export function replaceImpl < T > ( originalValue , newValue ) { return Lens . create < T , T > ( x => structEq ( x , originalValue ) ? newValue : x , conservatively ( ( y ) => structEq ( y , newValue ) ? originalValue : y ) ) ; } export function findImpl < T > ( predicate ) { return choose ( ( xs ) => { const i = findIndex ( xs , predicate ) ; return i < 0 ? Lens . nothing < T [ ] , T > ( ) : Lens . index < T > ( i ) ; } ) ; } declare module './base' { export namespace Lens { export let key ; example template TObject template TProperty param propExpr returns export let prop ; template TItem param i returns export let index ; param defaultValue export let withDefault ; /**
         * Create a lens that replaces a given value with a new one.
         */ export let replace ; /**
         * Create a prism that focuses on an array's element that
         * satisfies a given predicate.
         */ export let find ; } } Lens . key = keyImpl ; Lens . prop = propImpl ; Lens . index = indexImpl ; Lens . withDefault = withDefaultImpl ; Lens . replace = replaceImpl ; Lens . find = findImpl ;