123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471 |
- 'use strict';
- Object.defineProperty(exports, '__esModule', { value: true });
- var mobx = require('mobx');
- var livelinessChecking = "warn";
- /**
- * Defines what MST should do when running into reads / writes to objects that have died.
- * By default it will print a warning.
- * Use the `"error"` option to easy debugging to see where the error was thrown and when the offending read / write took place
- *
- * @param mode `"warn"`, `"error"` or `"ignore"`
- */
- function setLivelinessChecking(mode) {
- livelinessChecking = mode;
- }
- /**
- * Returns the current liveliness checking mode.
- *
- * @returns `"warn"`, `"error"` or `"ignore"`
- */
- function getLivelinessChecking() {
- return livelinessChecking;
- }
- /**
- * @deprecated use setLivelinessChecking instead
- * @hidden
- *
- * Defines what MST should do when running into reads / writes to objects that have died.
- * By default it will print a warning.
- * Use the `"error"` option to easy debugging to see where the error was thrown and when the offending read / write took place
- *
- * @param mode `"warn"`, `"error"` or `"ignore"`
- */
- function setLivelynessChecking(mode) {
- setLivelinessChecking(mode);
- }
- /**
- * @hidden
- */
- var Hook;
- (function (Hook) {
- Hook["afterCreate"] = "afterCreate";
- Hook["afterAttach"] = "afterAttach";
- Hook["afterCreationFinalization"] = "afterCreationFinalization";
- Hook["beforeDetach"] = "beforeDetach";
- Hook["beforeDestroy"] = "beforeDestroy";
- })(Hook || (Hook = {}));
- /*! *****************************************************************************
- Copyright (c) Microsoft Corporation. All rights reserved.
- Licensed under the Apache License, Version 2.0 (the "License"); you may not use
- this file except in compliance with the License. You may obtain a copy of the
- License at http://www.apache.org/licenses/LICENSE-2.0
- THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
- WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
- MERCHANTABLITY OR NON-INFRINGEMENT.
- See the Apache Version 2.0 License for specific language governing permissions
- and limitations under the License.
- ***************************************************************************** */
- /* global Reflect, Promise */
- var extendStatics = function(d, b) {
- extendStatics = Object.setPrototypeOf ||
- ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
- function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
- return extendStatics(d, b);
- };
- function __extends(d, b) {
- extendStatics(d, b);
- function __() { this.constructor = d; }
- d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
- }
- var __assign = function() {
- __assign = Object.assign || function __assign(t) {
- for (var s, i = 1, n = arguments.length; i < n; i++) {
- s = arguments[i];
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
- }
- return t;
- };
- return __assign.apply(this, arguments);
- };
- function __rest(s, e) {
- var t = {};
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
- t[p] = s[p];
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
- t[p[i]] = s[p[i]];
- }
- return t;
- }
- function __decorate(decorators, target, key, desc) {
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
- return c > 3 && r && Object.defineProperty(target, key, r), r;
- }
- function __values(o) {
- var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0;
- if (m) return m.call(o);
- return {
- next: function () {
- if (o && i >= o.length) o = void 0;
- return { value: o && o[i++], done: !o };
- }
- };
- }
- function __read(o, n) {
- var m = typeof Symbol === "function" && o[Symbol.iterator];
- if (!m) return o;
- var i = m.call(o), r, ar = [], e;
- try {
- while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
- }
- catch (error) { e = { error: error }; }
- finally {
- try {
- if (r && !r.done && (m = i["return"])) m.call(i);
- }
- finally { if (e) throw e.error; }
- }
- return ar;
- }
- function __spread() {
- for (var ar = [], i = 0; i < arguments.length; i++)
- ar = ar.concat(__read(arguments[i]));
- return ar;
- }
- /**
- * Returns the _actual_ type of the given tree node. (Or throws)
- *
- * @param object
- * @returns
- */
- function getType(object) {
- assertIsStateTreeNode(object, 1);
- return getStateTreeNode(object).type;
- }
- /**
- * Returns the _declared_ type of the given sub property of an object, array or map.
- * In the case of arrays and maps the property name is optional and will be ignored.
- *
- * Example:
- * ```ts
- * const Box = types.model({ x: 0, y: 0 })
- * const box = Box.create()
- *
- * console.log(getChildType(box, "x").name) // 'number'
- * ```
- *
- * @param object
- * @param propertyName
- * @returns
- */
- function getChildType(object, propertyName) {
- assertIsStateTreeNode(object, 1);
- return getStateTreeNode(object).getChildType(propertyName);
- }
- /**
- * Registers a function that will be invoked for each mutation that is applied to the provided model instance, or to any of its children.
- * See [patches](https://github.com/mobxjs/mobx-state-tree#patches) for more details. onPatch events are emitted immediately and will not await the end of a transaction.
- * Patches can be used to deep observe a model tree.
- *
- * @param target the model instance from which to receive patches
- * @param callback the callback that is invoked for each patch. The reversePatch is a patch that would actually undo the emitted patch
- * @returns function to remove the listener
- */
- function onPatch(target, callback) {
- // check all arguments
- assertIsStateTreeNode(target, 1);
- assertIsFunction(callback, 2);
- return getStateTreeNode(target).onPatch(callback);
- }
- /**
- * Registers a function that is invoked whenever a new snapshot for the given model instance is available.
- * The listener will only be fire at the end of the current MobX (trans)action.
- * See [snapshots](https://github.com/mobxjs/mobx-state-tree#snapshots) for more details.
- *
- * @param target
- * @param callback
- * @returns
- */
- function onSnapshot(target, callback) {
- // check all arguments
- assertIsStateTreeNode(target, 1);
- assertIsFunction(callback, 2);
- return getStateTreeNode(target).onSnapshot(callback);
- }
- /**
- * Applies a JSON-patch to the given model instance or bails out if the patch couldn't be applied
- * See [patches](https://github.com/mobxjs/mobx-state-tree#patches) for more details.
- *
- * Can apply a single past, or an array of patches.
- *
- * @param target
- * @param patch
- * @returns
- */
- function applyPatch(target, patch) {
- // check all arguments
- assertIsStateTreeNode(target, 1);
- assertArg(patch, function (p) { return typeof p === "object"; }, "object or array", 2);
- getStateTreeNode(target).applyPatches(asArray(patch));
- }
- /**
- * Small abstraction around `onPatch` and `applyPatch`, attaches a patch listener to a tree and records all the patches.
- * Returns an recorder object with the following signature:
- *
- * Example:
- * ```ts
- * export interface IPatchRecorder {
- * // the recorded patches
- * patches: IJsonPatch[]
- * // the inverse of the recorded patches
- * inversePatches: IJsonPatch[]
- * // true if currently recording
- * recording: boolean
- * // stop recording patches
- * stop(): void
- * // resume recording patches
- * resume(): void
- * // apply all the recorded patches on the given target (the original subject if omitted)
- * replay(target?: IAnyStateTreeNode): void
- * // reverse apply the recorded patches on the given target (the original subject if omitted)
- * // stops the recorder if not already stopped
- * undo(): void
- * }
- * ```
- *
- * The optional filter function allows to skip recording certain patches.
- *
- * @param subject
- * @param filter
- * @returns
- */
- function recordPatches(subject, filter) {
- // check all arguments
- assertIsStateTreeNode(subject, 1);
- var data = {
- patches: [],
- reversedInversePatches: []
- };
- // we will generate the immutable copy of patches on demand for public consumption
- var publicData = {};
- var disposer;
- var recorder = {
- get recording() {
- return !!disposer;
- },
- get patches() {
- if (!publicData.patches) {
- publicData.patches = data.patches.slice();
- }
- return publicData.patches;
- },
- get reversedInversePatches() {
- if (!publicData.reversedInversePatches) {
- publicData.reversedInversePatches = data.reversedInversePatches.slice();
- }
- return publicData.reversedInversePatches;
- },
- get inversePatches() {
- if (!publicData.inversePatches) {
- publicData.inversePatches = data.reversedInversePatches.slice().reverse();
- }
- return publicData.inversePatches;
- },
- stop: function () {
- if (disposer) {
- disposer();
- disposer = undefined;
- }
- },
- resume: function () {
- if (disposer)
- return;
- disposer = onPatch(subject, function (patch, inversePatch) {
- // skip patches that are asked to be filtered if there's a filter in place
- if (filter && !filter(patch, inversePatch, getRunningActionContext())) {
- return;
- }
- data.patches.push(patch);
- data.reversedInversePatches.unshift(inversePatch);
- // mark immutable public patches as dirty
- publicData.patches = undefined;
- publicData.inversePatches = undefined;
- publicData.reversedInversePatches = undefined;
- });
- },
- replay: function (target) {
- applyPatch(target || subject, data.patches);
- },
- undo: function (target) {
- applyPatch(target || subject, data.reversedInversePatches);
- }
- };
- recorder.resume();
- return recorder;
- }
- /**
- * The inverse of `unprotect`.
- *
- * @param target
- */
- function protect(target) {
- // check all arguments
- assertIsStateTreeNode(target, 1);
- var node = getStateTreeNode(target);
- if (!node.isRoot)
- throw fail$1("`protect` can only be invoked on root nodes");
- node.isProtectionEnabled = true;
- }
- /**
- * By default it is not allowed to directly modify a model. Models can only be modified through actions.
- * However, in some cases you don't care about the advantages (like replayability, traceability, etc) this yields.
- * For example because you are building a PoC or don't have any middleware attached to your tree.
- *
- * In that case you can disable this protection by calling `unprotect` on the root of your tree.
- *
- * Example:
- * ```ts
- * const Todo = types.model({
- * done: false
- * }).actions(self => ({
- * toggle() {
- * self.done = !self.done
- * }
- * }))
- *
- * const todo = Todo.create()
- * todo.done = true // throws!
- * todo.toggle() // OK
- * unprotect(todo)
- * todo.done = false // OK
- * ```
- */
- function unprotect(target) {
- // check all arguments
- assertIsStateTreeNode(target, 1);
- var node = getStateTreeNode(target);
- if (!node.isRoot)
- throw fail$1("`unprotect` can only be invoked on root nodes");
- node.isProtectionEnabled = false;
- }
- /**
- * Returns true if the object is in protected mode, @see protect
- */
- function isProtected(target) {
- return getStateTreeNode(target).isProtected;
- }
- /**
- * Applies a snapshot to a given model instances. Patch and snapshot listeners will be invoked as usual.
- *
- * @param target
- * @param snapshot
- * @returns
- */
- function applySnapshot(target, snapshot) {
- // check all arguments
- assertIsStateTreeNode(target, 1);
- return getStateTreeNode(target).applySnapshot(snapshot);
- }
- /**
- * Calculates a snapshot from the given model instance. The snapshot will always reflect the latest state but use
- * structural sharing where possible. Doesn't require MobX transactions to be completed.
- *
- * @param target
- * @param applyPostProcess If true (the default) then postProcessSnapshot gets applied.
- * @returns
- */
- function getSnapshot(target, applyPostProcess) {
- if (applyPostProcess === void 0) { applyPostProcess = true; }
- // check all arguments
- assertIsStateTreeNode(target, 1);
- var node = getStateTreeNode(target);
- if (applyPostProcess)
- return node.snapshot;
- return freeze(node.type.getSnapshot(node, false));
- }
- /**
- * Given a model instance, returns `true` if the object has a parent, that is, is part of another object, map or array.
- *
- * @param target
- * @param depth How far should we look upward? 1 by default.
- * @returns
- */
- function hasParent(target, depth) {
- if (depth === void 0) { depth = 1; }
- // check all arguments
- assertIsStateTreeNode(target, 1);
- assertIsNumber(depth, 2, 0);
- var parent = getStateTreeNode(target).parent;
- while (parent) {
- if (--depth === 0)
- return true;
- parent = parent.parent;
- }
- return false;
- }
- /**
- * Returns the immediate parent of this object, or throws.
- *
- * Note that the immediate parent can be either an object, map or array, and
- * doesn't necessarily refer to the parent model.
- *
- * Please note that in child nodes access to the root is only possible
- * once the `afterAttach` hook has fired.
- *
- * @param target
- * @param depth How far should we look upward? 1 by default.
- * @returns
- */
- function getParent(target, depth) {
- if (depth === void 0) { depth = 1; }
- // check all arguments
- assertIsStateTreeNode(target, 1);
- assertIsNumber(depth, 2, 0);
- var d = depth;
- var parent = getStateTreeNode(target).parent;
- while (parent) {
- if (--d === 0)
- return parent.storedValue;
- parent = parent.parent;
- }
- throw fail$1("Failed to find the parent of " + getStateTreeNode(target) + " at depth " + depth);
- }
- /**
- * Given a model instance, returns `true` if the object has a parent of given type, that is, is part of another object, map or array
- *
- * @param target
- * @param type
- * @returns
- */
- function hasParentOfType(target, type) {
- // check all arguments
- assertIsStateTreeNode(target, 1);
- assertIsType(type, 2);
- var parent = getStateTreeNode(target).parent;
- while (parent) {
- if (type.is(parent.storedValue))
- return true;
- parent = parent.parent;
- }
- return false;
- }
- /**
- * Returns the target's parent of a given type, or throws.
- *
- * @param target
- * @param type
- * @returns
- */
- function getParentOfType(target, type) {
- // check all arguments
- assertIsStateTreeNode(target, 1);
- assertIsType(type, 2);
- var parent = getStateTreeNode(target).parent;
- while (parent) {
- if (type.is(parent.storedValue))
- return parent.storedValue;
- parent = parent.parent;
- }
- throw fail$1("Failed to find the parent of " + getStateTreeNode(target) + " of a given type");
- }
- /**
- * Given an object in a model tree, returns the root object of that tree.
- *
- * Please note that in child nodes access to the root is only possible
- * once the `afterAttach` hook has fired.
- *
- * @param target
- * @returns
- */
- function getRoot(target) {
- // check all arguments
- assertIsStateTreeNode(target, 1);
- return getStateTreeNode(target).root.storedValue;
- }
- /**
- * Returns the path of the given object in the model tree
- *
- * @param target
- * @returns
- */
- function getPath(target) {
- // check all arguments
- assertIsStateTreeNode(target, 1);
- return getStateTreeNode(target).path;
- }
- /**
- * Returns the path of the given object as unescaped string array.
- *
- * @param target
- * @returns
- */
- function getPathParts(target) {
- // check all arguments
- assertIsStateTreeNode(target, 1);
- return splitJsonPath(getStateTreeNode(target).path);
- }
- /**
- * Returns true if the given object is the root of a model tree.
- *
- * @param target
- * @returns
- */
- function isRoot(target) {
- // check all arguments
- assertIsStateTreeNode(target, 1);
- return getStateTreeNode(target).isRoot;
- }
- /**
- * Resolves a path relatively to a given object.
- * Returns undefined if no value can be found.
- *
- * @param target
- * @param path escaped json path
- * @returns
- */
- function resolvePath(target, path) {
- // check all arguments
- assertIsStateTreeNode(target, 1);
- assertIsString(path, 2);
- var node = resolveNodeByPath(getStateTreeNode(target), path);
- return node ? node.value : undefined;
- }
- /**
- * Resolves a model instance given a root target, the type and the identifier you are searching for.
- * Returns undefined if no value can be found.
- *
- * @param type
- * @param target
- * @param identifier
- * @returns
- */
- function resolveIdentifier(type, target, identifier) {
- // check all arguments
- assertIsType(type, 1);
- assertIsStateTreeNode(target, 2);
- assertIsValidIdentifier(identifier, 3);
- var node = getStateTreeNode(target).root.identifierCache.resolve(type, normalizeIdentifier(identifier));
- return node ? node.value : undefined;
- }
- /**
- * Returns the identifier of the target node.
- * This is the *string normalized* identifier, which might not match the type of the identifier attribute
- *
- * @param target
- * @returns
- */
- function getIdentifier(target) {
- // check all arguments
- assertIsStateTreeNode(target, 1);
- return getStateTreeNode(target).identifier;
- }
- /**
- * Tests if a reference is valid (pointing to an existing node and optionally if alive) and returns such reference if it the check passes,
- * else it returns undefined.
- *
- * @param getter Function to access the reference.
- * @param checkIfAlive true to also make sure the referenced node is alive (default), false to skip this check.
- * @returns
- */
- function tryReference(getter, checkIfAlive) {
- if (checkIfAlive === void 0) { checkIfAlive = true; }
- try {
- var node = getter();
- if (node === undefined || node === null) {
- return undefined;
- }
- else if (isStateTreeNode(node)) {
- if (!checkIfAlive) {
- return node;
- }
- else {
- return isAlive(node) ? node : undefined;
- }
- }
- else {
- throw fail$1("The reference to be checked is not one of node, null or undefined");
- }
- }
- catch (e) {
- if (e instanceof InvalidReferenceError) {
- return undefined;
- }
- throw e;
- }
- }
- /**
- * Tests if a reference is valid (pointing to an existing node and optionally if alive) and returns if the check passes or not.
- *
- * @param getter Function to access the reference.
- * @param checkIfAlive true to also make sure the referenced node is alive (default), false to skip this check.
- * @returns
- */
- function isValidReference(getter, checkIfAlive) {
- if (checkIfAlive === void 0) { checkIfAlive = true; }
- try {
- var node = getter();
- if (node === undefined || node === null) {
- return false;
- }
- else if (isStateTreeNode(node)) {
- return checkIfAlive ? isAlive(node) : true;
- }
- else {
- throw fail$1("The reference to be checked is not one of node, null or undefined");
- }
- }
- catch (e) {
- if (e instanceof InvalidReferenceError) {
- return false;
- }
- throw e;
- }
- }
- /**
- * Try to resolve a given path relative to a given node.
- *
- * @param target
- * @param path
- * @returns
- */
- function tryResolve(target, path) {
- // check all arguments
- assertIsStateTreeNode(target, 1);
- assertIsString(path, 2);
- var node = resolveNodeByPath(getStateTreeNode(target), path, false);
- if (node === undefined)
- return undefined;
- try {
- return node.value;
- }
- catch (e) {
- // For what ever reason not resolvable (e.g. totally not existing path, or value that cannot be fetched)
- // see test / issue: 'try resolve doesn't work #686'
- return undefined;
- }
- }
- /**
- * Given two state tree nodes that are part of the same tree,
- * returns the shortest jsonpath needed to navigate from the one to the other
- *
- * @param base
- * @param target
- * @returns
- */
- function getRelativePath(base, target) {
- // check all arguments
- assertIsStateTreeNode(base, 1);
- assertIsStateTreeNode(target, 2);
- return getRelativePathBetweenNodes(getStateTreeNode(base), getStateTreeNode(target));
- }
- /**
- * Returns a deep copy of the given state tree node as new tree.
- * Short hand for `snapshot(x) = getType(x).create(getSnapshot(x))`
- *
- * _Tip: clone will create a literal copy, including the same identifiers. To modify identifiers etc during cloning, don't use clone but take a snapshot of the tree, modify it, and create new instance_
- *
- * @param source
- * @param keepEnvironment indicates whether the clone should inherit the same environment (`true`, the default), or not have an environment (`false`). If an object is passed in as second argument, that will act as the environment for the cloned tree.
- * @returns
- */
- function clone(source, keepEnvironment) {
- if (keepEnvironment === void 0) { keepEnvironment = true; }
- // check all arguments
- assertIsStateTreeNode(source, 1);
- var node = getStateTreeNode(source);
- return node.type.create(node.snapshot, keepEnvironment === true
- ? node.root.environment
- : keepEnvironment === false
- ? undefined
- : keepEnvironment); // it's an object or something else
- }
- /**
- * Removes a model element from the state tree, and let it live on as a new state tree
- */
- function detach(target) {
- // check all arguments
- assertIsStateTreeNode(target, 1);
- getStateTreeNode(target).detach();
- return target;
- }
- /**
- * Removes a model element from the state tree, and mark it as end-of-life; the element should not be used anymore
- */
- function destroy(target) {
- // check all arguments
- assertIsStateTreeNode(target, 1);
- var node = getStateTreeNode(target);
- if (node.isRoot)
- node.die();
- else
- node.parent.removeChild(node.subpath);
- }
- /**
- * Returns true if the given state tree node is not killed yet.
- * This means that the node is still a part of a tree, and that `destroy`
- * has not been called. If a node is not alive anymore, the only thing one can do with it
- * is requesting it's last path and snapshot
- *
- * @param target
- * @returns
- */
- function isAlive(target) {
- // check all arguments
- assertIsStateTreeNode(target, 1);
- return getStateTreeNode(target).observableIsAlive;
- }
- /**
- * Use this utility to register a function that should be called whenever the
- * targeted state tree node is destroyed. This is a useful alternative to managing
- * cleanup methods yourself using the `beforeDestroy` hook.
- *
- * This methods returns the same disposer that was passed as argument.
- *
- * Example:
- * ```ts
- * const Todo = types.model({
- * title: types.string
- * }).actions(self => ({
- * afterCreate() {
- * const autoSaveDisposer = reaction(
- * () => getSnapshot(self),
- * snapshot => sendSnapshotToServerSomehow(snapshot)
- * )
- * // stop sending updates to server if this
- * // instance is destroyed
- * addDisposer(self, autoSaveDisposer)
- * }
- * }))
- * ```
- *
- * @param target
- * @param disposer
- * @returns The same disposer that was passed as argument
- */
- function addDisposer(target, disposer) {
- // check all arguments
- assertIsStateTreeNode(target, 1);
- assertIsFunction(disposer, 2);
- var node = getStateTreeNode(target);
- node.addDisposer(disposer);
- return disposer;
- }
- /**
- * Returns the environment of the current state tree. For more info on environments,
- * see [Dependency injection](https://github.com/mobxjs/mobx-state-tree#dependency-injection)
- *
- * Please note that in child nodes access to the root is only possible
- * once the `afterAttach` hook has fired
- *
- * Returns an empty environment if the tree wasn't initialized with an environment
- *
- * @param target
- * @returns
- */
- function getEnv(target) {
- // check all arguments
- assertIsStateTreeNode(target, 1);
- var node = getStateTreeNode(target);
- var env = node.root.environment;
- if (!env)
- return EMPTY_OBJECT;
- return env;
- }
- /**
- * Performs a depth first walk through a tree.
- */
- function walk(target, processor) {
- // check all arguments
- assertIsStateTreeNode(target, 1);
- assertIsFunction(processor, 2);
- var node = getStateTreeNode(target);
- // tslint:disable-next-line:no_unused-variable
- node.getChildren().forEach(function (child) {
- if (isStateTreeNode(child.storedValue))
- walk(child.storedValue, processor);
- });
- processor(node.storedValue);
- }
- /**
- * Returns a reflection of the model type properties and name for either a model type or model node.
- *
- * @param typeOrNode
- * @returns
- */
- function getPropertyMembers(typeOrNode) {
- var type;
- if (isStateTreeNode(typeOrNode)) {
- type = getType(typeOrNode);
- }
- else {
- type = typeOrNode;
- }
- assertArg(type, function (t) { return isModelType(t); }, "model type or model instance", 1);
- return {
- name: type.name,
- properties: __assign({}, type.properties)
- };
- }
- /**
- * Returns a reflection of the model node, including name, properties, views, volatile and actions.
- *
- * @param target
- * @returns
- */
- function getMembers(target) {
- var type = getStateTreeNode(target).type;
- var reflected = __assign(__assign({}, getPropertyMembers(type)), { actions: [], volatile: [], views: [] });
- var props = Object.getOwnPropertyNames(target);
- props.forEach(function (key) {
- if (key in reflected.properties)
- return;
- var descriptor = Object.getOwnPropertyDescriptor(target, key);
- if (descriptor.get) {
- if (mobx.isComputedProp(target, key))
- reflected.views.push(key);
- else
- reflected.volatile.push(key);
- return;
- }
- if (descriptor.value._isMSTAction === true)
- reflected.actions.push(key);
- else if (mobx.isObservableProp(target, key))
- reflected.volatile.push(key);
- else
- reflected.views.push(key);
- });
- return reflected;
- }
- /**
- * Casts a node snapshot or instance type to an instance type so it can be assigned to a type instance.
- * Note that this is just a cast for the type system, this is, it won't actually convert a snapshot to an instance,
- * but just fool typescript into thinking so.
- * Either way, casting when outside an assignation operation won't compile.
- *
- * Example:
- * ```ts
- * const ModelA = types.model({
- * n: types.number
- * }).actions(self => ({
- * setN(aNumber: number) {
- * self.n = aNumber
- * }
- * }))
- *
- * const ModelB = types.model({
- * innerModel: ModelA
- * }).actions(self => ({
- * someAction() {
- * // this will allow the compiler to assign a snapshot to the property
- * self.innerModel = cast({ a: 5 })
- * }
- * }))
- * ```
- *
- * @param snapshotOrInstance Snapshot or instance
- * @returns The same object casted as an instance
- */
- function cast(snapshotOrInstance) {
- return snapshotOrInstance;
- }
- /**
- * Casts a node instance type to an snapshot type so it can be assigned to a type snapshot (e.g. to be used inside a create call).
- * Note that this is just a cast for the type system, this is, it won't actually convert an instance to a snapshot,
- * but just fool typescript into thinking so.
- *
- * Example:
- * ```ts
- * const ModelA = types.model({
- * n: types.number
- * }).actions(self => ({
- * setN(aNumber: number) {
- * self.n = aNumber
- * }
- * }))
- *
- * const ModelB = types.model({
- * innerModel: ModelA
- * })
- *
- * const a = ModelA.create({ n: 5 });
- * // this will allow the compiler to use a model as if it were a snapshot
- * const b = ModelB.create({ innerModel: castToSnapshot(a)})
- * ```
- *
- * @param snapshotOrInstance Snapshot or instance
- * @returns The same object casted as an input (creation) snapshot
- */
- function castToSnapshot(snapshotOrInstance) {
- return snapshotOrInstance;
- }
- /**
- * Casts a node instance type to a reference snapshot type so it can be assigned to a refernence snapshot (e.g. to be used inside a create call).
- * Note that this is just a cast for the type system, this is, it won't actually convert an instance to a refererence snapshot,
- * but just fool typescript into thinking so.
- *
- * Example:
- * ```ts
- * const ModelA = types.model({
- * id: types.identifier,
- * n: types.number
- * }).actions(self => ({
- * setN(aNumber: number) {
- * self.n = aNumber
- * }
- * }))
- *
- * const ModelB = types.model({
- * refA: types.reference(ModelA)
- * })
- *
- * const a = ModelA.create({ id: 'someId', n: 5 });
- * // this will allow the compiler to use a model as if it were a reference snapshot
- * const b = ModelB.create({ refA: castToReference(a)})
- * ```
- *
- * @param instance Instance
- * @returns The same object casted as an reference snapshot (string or number)
- */
- function castToReferenceSnapshot(instance) {
- return instance;
- }
- /**
- * Returns the unique node id (not to be confused with the instance identifier) for a
- * given instance.
- * This id is a number that is unique for each instance.
- *
- * @export
- * @param target
- * @returns
- */
- function getNodeId(target) {
- assertIsStateTreeNode(target, 1);
- return getStateTreeNode(target).nodeId;
- }
- /**
- * @internal
- * @hidden
- */
- var BaseNode = /** @class */ (function () {
- function BaseNode(type, parent, subpath, environment) {
- this.type = type;
- this.environment = environment;
- this._state = NodeLifeCycle.INITIALIZING;
- this.environment = environment;
- this.baseSetParent(parent, subpath);
- }
- Object.defineProperty(BaseNode.prototype, "subpath", {
- get: function () {
- return this._subpath;
- },
- enumerable: true,
- configurable: true
- });
- Object.defineProperty(BaseNode.prototype, "subpathUponDeath", {
- get: function () {
- return this._subpathUponDeath;
- },
- enumerable: true,
- configurable: true
- });
- Object.defineProperty(BaseNode.prototype, "pathUponDeath", {
- get: function () {
- return this._pathUponDeath;
- },
- enumerable: true,
- configurable: true
- });
- Object.defineProperty(BaseNode.prototype, "value", {
- get: function () {
- return this.type.getValue(this);
- },
- enumerable: true,
- configurable: true
- });
- Object.defineProperty(BaseNode.prototype, "state", {
- get: function () {
- return this._state;
- },
- set: function (val) {
- var wasAlive = this.isAlive;
- this._state = val;
- var isAlive = this.isAlive;
- if (this.aliveAtom && wasAlive !== isAlive) {
- this.aliveAtom.reportChanged();
- }
- },
- enumerable: true,
- configurable: true
- });
- BaseNode.prototype.fireInternalHook = function (name) {
- if (this._hookSubscribers) {
- this._hookSubscribers.emit(name, this, name);
- }
- };
- BaseNode.prototype.registerHook = function (hook, hookHandler) {
- if (!this._hookSubscribers) {
- this._hookSubscribers = new EventHandlers();
- }
- return this._hookSubscribers.register(hook, hookHandler);
- };
- Object.defineProperty(BaseNode.prototype, "parent", {
- get: function () {
- return this._parent;
- },
- enumerable: true,
- configurable: true
- });
- BaseNode.prototype.baseSetParent = function (parent, subpath) {
- this._parent = parent;
- this._subpath = subpath;
- this._escapedSubpath = undefined; // regenerate when needed
- if (this.pathAtom) {
- this.pathAtom.reportChanged();
- }
- };
- Object.defineProperty(BaseNode.prototype, "path", {
- /*
- * Returns (escaped) path representation as string
- */
- get: function () {
- return this.getEscapedPath(true);
- },
- enumerable: true,
- configurable: true
- });
- BaseNode.prototype.getEscapedPath = function (reportObserved) {
- if (reportObserved) {
- if (!this.pathAtom) {
- this.pathAtom = mobx.createAtom("path");
- }
- this.pathAtom.reportObserved();
- }
- if (!this.parent)
- return "";
- // regenerate escaped subpath if needed
- if (this._escapedSubpath === undefined) {
- this._escapedSubpath = !this._subpath ? "" : escapeJsonPath(this._subpath);
- }
- return this.parent.getEscapedPath(reportObserved) + "/" + this._escapedSubpath;
- };
- Object.defineProperty(BaseNode.prototype, "isRoot", {
- get: function () {
- return this.parent === null;
- },
- enumerable: true,
- configurable: true
- });
- Object.defineProperty(BaseNode.prototype, "isAlive", {
- get: function () {
- return this.state !== NodeLifeCycle.DEAD;
- },
- enumerable: true,
- configurable: true
- });
- Object.defineProperty(BaseNode.prototype, "isDetaching", {
- get: function () {
- return this.state === NodeLifeCycle.DETACHING;
- },
- enumerable: true,
- configurable: true
- });
- Object.defineProperty(BaseNode.prototype, "observableIsAlive", {
- get: function () {
- if (!this.aliveAtom) {
- this.aliveAtom = mobx.createAtom("alive");
- }
- this.aliveAtom.reportObserved();
- return this.isAlive;
- },
- enumerable: true,
- configurable: true
- });
- BaseNode.prototype.baseFinalizeCreation = function (whenFinalized) {
- if (devMode()) {
- if (!this.isAlive) {
- // istanbul ignore next
- throw fail("assertion failed: cannot finalize the creation of a node that is already dead");
- }
- }
- // goal: afterCreate hooks runs depth-first. After attach runs parent first, so on afterAttach the parent has completed already
- if (this.state === NodeLifeCycle.CREATED) {
- if (this.parent) {
- if (this.parent.state !== NodeLifeCycle.FINALIZED) {
- // parent not ready yet, postpone
- return;
- }
- this.fireHook(Hook.afterAttach);
- }
- this.state = NodeLifeCycle.FINALIZED;
- if (whenFinalized) {
- whenFinalized();
- }
- }
- };
- BaseNode.prototype.baseFinalizeDeath = function () {
- if (this._hookSubscribers) {
- this._hookSubscribers.clearAll();
- }
- this._subpathUponDeath = this._subpath;
- this._pathUponDeath = this.getEscapedPath(false);
- this.baseSetParent(null, "");
- this.state = NodeLifeCycle.DEAD;
- };
- BaseNode.prototype.baseAboutToDie = function () {
- this.fireHook(Hook.beforeDestroy);
- };
- return BaseNode;
- }());
- /**
- * @internal
- * @hidden
- */
- var ScalarNode = /** @class */ (function (_super) {
- __extends(ScalarNode, _super);
- function ScalarNode(simpleType, parent, subpath, environment, initialSnapshot) {
- var _this = _super.call(this, simpleType, parent, subpath, environment) || this;
- try {
- _this.storedValue = simpleType.createNewInstance(initialSnapshot);
- }
- catch (e) {
- // short-cut to die the instance, to avoid the snapshot computed starting to throw...
- _this.state = NodeLifeCycle.DEAD;
- throw e;
- }
- _this.state = NodeLifeCycle.CREATED;
- // for scalar nodes there's no point in firing this event since it would fire on the constructor, before
- // anybody can actually register for/listen to it
- // this.fireHook(Hook.AfterCreate)
- _this.finalizeCreation();
- return _this;
- }
- Object.defineProperty(ScalarNode.prototype, "root", {
- get: function () {
- // future optimization: store root ref in the node and maintain it
- if (!this.parent)
- throw fail$1("This scalar node is not part of a tree");
- return this.parent.root;
- },
- enumerable: true,
- configurable: true
- });
- ScalarNode.prototype.setParent = function (newParent, subpath) {
- var parentChanged = this.parent !== newParent;
- var subpathChanged = this.subpath !== subpath;
- if (!parentChanged && !subpathChanged) {
- return;
- }
- if (devMode()) {
- if (!subpath) {
- // istanbul ignore next
- throw fail$1("assertion failed: subpath expected");
- }
- if (!newParent) {
- // istanbul ignore next
- throw fail$1("assertion failed: parent expected");
- }
- if (parentChanged) {
- // istanbul ignore next
- throw fail$1("assertion failed: scalar nodes cannot change their parent");
- }
- }
- this.environment = undefined; // use parent's
- this.baseSetParent(this.parent, subpath);
- };
- Object.defineProperty(ScalarNode.prototype, "snapshot", {
- get: function () {
- return freeze(this.getSnapshot());
- },
- enumerable: true,
- configurable: true
- });
- ScalarNode.prototype.getSnapshot = function () {
- return this.type.getSnapshot(this);
- };
- ScalarNode.prototype.toString = function () {
- var path = (this.isAlive ? this.path : this.pathUponDeath) || "<root>";
- return this.type.name + "@" + path + (this.isAlive ? "" : " [dead]");
- };
- ScalarNode.prototype.die = function () {
- if (!this.isAlive || this.state === NodeLifeCycle.DETACHING)
- return;
- this.aboutToDie();
- this.finalizeDeath();
- };
- ScalarNode.prototype.finalizeCreation = function () {
- this.baseFinalizeCreation();
- };
- ScalarNode.prototype.aboutToDie = function () {
- this.baseAboutToDie();
- };
- ScalarNode.prototype.finalizeDeath = function () {
- this.baseFinalizeDeath();
- };
- ScalarNode.prototype.fireHook = function (name) {
- this.fireInternalHook(name);
- };
- __decorate([
- mobx.action
- ], ScalarNode.prototype, "die", null);
- return ScalarNode;
- }(BaseNode));
- var nextNodeId = 1;
- var snapshotReactionOptions = {
- onError: function (e) {
- throw e;
- }
- };
- /**
- * @internal
- * @hidden
- */
- var ObjectNode = /** @class */ (function (_super) {
- __extends(ObjectNode, _super);
- function ObjectNode(complexType, parent, subpath, environment, initialValue) {
- var _this = _super.call(this, complexType, parent, subpath, environment) || this;
- _this.nodeId = ++nextNodeId;
- _this.isProtectionEnabled = true;
- _this._autoUnbox = true; // unboxing is disabled when reading child nodes
- _this._isRunningAction = false; // only relevant for root
- _this._hasSnapshotReaction = false;
- _this._observableInstanceState = 0 /* UNINITIALIZED */;
- _this._cachedInitialSnapshotCreated = false;
- _this.unbox = _this.unbox.bind(_this);
- _this._initialSnapshot = freeze(initialValue);
- _this.identifierAttribute = complexType.identifierAttribute;
- if (!parent) {
- _this.identifierCache = new IdentifierCache();
- }
- _this._childNodes = complexType.initializeChildNodes(_this, _this._initialSnapshot);
- // identifier can not be changed during lifecycle of a node
- // so we safely can read it from initial snapshot
- _this.identifier = null;
- _this.unnormalizedIdentifier = null;
- if (_this.identifierAttribute && _this._initialSnapshot) {
- var id = _this._initialSnapshot[_this.identifierAttribute];
- if (id === undefined) {
- // try with the actual node if not (for optional identifiers)
- var childNode = _this._childNodes[_this.identifierAttribute];
- if (childNode) {
- id = childNode.value;
- }
- }
- if (typeof id !== "string" && typeof id !== "number") {
- throw fail$1("Instance identifier '" + _this.identifierAttribute + "' for type '" + _this.type.name + "' must be a string or a number");
- }
- // normalize internal identifier to string
- _this.identifier = normalizeIdentifier(id);
- _this.unnormalizedIdentifier = id;
- }
- if (!parent) {
- _this.identifierCache.addNodeToCache(_this);
- }
- else {
- parent.root.identifierCache.addNodeToCache(_this);
- }
- return _this;
- }
- ObjectNode.prototype.applyPatches = function (patches) {
- this.createObservableInstanceIfNeeded();
- this._applyPatches(patches);
- };
- ObjectNode.prototype.applySnapshot = function (snapshot) {
- this.createObservableInstanceIfNeeded();
- this._applySnapshot(snapshot);
- };
- ObjectNode.prototype.createObservableInstanceIfNeeded = function () {
- var e_1, _a;
- if (this._observableInstanceState !== 0 /* UNINITIALIZED */) {
- return;
- }
- if (devMode()) {
- if (this.state !== NodeLifeCycle.INITIALIZING) {
- // istanbul ignore next
- throw fail$1("assertion failed: the creation of the observable instance must be done on the initializing phase");
- }
- }
- this._observableInstanceState = 1 /* CREATING */;
- // make sure the parent chain is created as well
- // array with parent chain from parent to child
- var parentChain = [];
- var parent = this.parent;
- // for performance reasons we never go back further than the most direct
- // uninitialized parent
- // this is done to avoid traversing the whole tree to the root when using
- // the same reference again
- while (parent &&
- parent._observableInstanceState === 0 /* UNINITIALIZED */) {
- parentChain.unshift(parent);
- parent = parent.parent;
- }
- try {
- // initialize the uninitialized parent chain from parent to child
- for (var parentChain_1 = __values(parentChain), parentChain_1_1 = parentChain_1.next(); !parentChain_1_1.done; parentChain_1_1 = parentChain_1.next()) {
- var p = parentChain_1_1.value;
- p.createObservableInstanceIfNeeded();
- }
- }
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
- finally {
- try {
- if (parentChain_1_1 && !parentChain_1_1.done && (_a = parentChain_1.return)) _a.call(parentChain_1);
- }
- finally { if (e_1) throw e_1.error; }
- }
- var type = this.type;
- try {
- this.storedValue = type.createNewInstance(this._childNodes);
- this.preboot();
- this._isRunningAction = true;
- type.finalizeNewInstance(this, this.storedValue);
- }
- catch (e) {
- // short-cut to die the instance, to avoid the snapshot computed starting to throw...
- this.state = NodeLifeCycle.DEAD;
- throw e;
- }
- finally {
- this._isRunningAction = false;
- }
- this._observableInstanceState = 2 /* CREATED */;
- // NOTE: we need to touch snapshot, because non-observable
- // "_observableInstanceState" field was touched
- invalidateComputed(this, "snapshot");
- if (this.isRoot)
- this._addSnapshotReaction();
- this._childNodes = EMPTY_OBJECT;
- this.state = NodeLifeCycle.CREATED;
- this.fireHook(Hook.afterCreate);
- this.finalizeCreation();
- };
- Object.defineProperty(ObjectNode.prototype, "root", {
- get: function () {
- var parent = this.parent;
- return parent ? parent.root : this;
- },
- enumerable: true,
- configurable: true
- });
- ObjectNode.prototype.clearParent = function () {
- if (!this.parent)
- return;
- // detach if attached
- this.fireHook(Hook.beforeDetach);
- var previousState = this.state;
- this.state = NodeLifeCycle.DETACHING;
- var root = this.root;
- var newEnv = root.environment;
- var newIdCache = root.identifierCache.splitCache(this);
- try {
- this.parent.removeChild(this.subpath);
- this.baseSetParent(null, "");
- this.environment = newEnv;
- this.identifierCache = newIdCache;
- }
- finally {
- this.state = previousState;
- }
- };
- ObjectNode.prototype.setParent = function (newParent, subpath) {
- var parentChanged = newParent !== this.parent;
- var subpathChanged = subpath !== this.subpath;
- if (!parentChanged && !subpathChanged) {
- return;
- }
- if (devMode()) {
- if (!subpath) {
- // istanbul ignore next
- throw fail$1("assertion failed: subpath expected");
- }
- if (!newParent) {
- // istanbul ignore next
- throw fail$1("assertion failed: new parent expected");
- }
- if (this.parent && parentChanged) {
- throw fail$1("A node cannot exists twice in the state tree. Failed to add " + this + " to path '" + newParent.path + "/" + subpath + "'.");
- }
- if (!this.parent && newParent.root === this) {
- throw fail$1("A state tree is not allowed to contain itself. Cannot assign " + this + " to path '" + newParent.path + "/" + subpath + "'");
- }
- if (!this.parent &&
- !!this.environment &&
- this.environment !== newParent.root.environment) {
- throw fail$1("A state tree cannot be made part of another state tree as long as their environments are different.");
- }
- }
- if (parentChanged) {
- // attach to new parent
- this.environment = undefined; // will use root's
- newParent.root.identifierCache.mergeCache(this);
- this.baseSetParent(newParent, subpath);
- this.fireHook(Hook.afterAttach);
- }
- else if (subpathChanged) {
- // moving to a new subpath on the same parent
- this.baseSetParent(this.parent, subpath);
- }
- };
- ObjectNode.prototype.fireHook = function (name) {
- var _this = this;
- this.fireInternalHook(name);
- var fn = this.storedValue &&
- typeof this.storedValue === "object" &&
- this.storedValue[name];
- if (typeof fn === "function") {
- // we check for it to allow old mobx peer dependencies that don't have the method to work (even when still bugged)
- if (mobx._allowStateChangesInsideComputed) {
- mobx._allowStateChangesInsideComputed(function () {
- fn.apply(_this.storedValue);
- });
- }
- else {
- fn.apply(this.storedValue);
- }
- }
- };
- Object.defineProperty(ObjectNode.prototype, "snapshot", {
- // advantage of using computed for a snapshot is that nicely respects transactions etc.
- get: function () {
- return freeze(this.getSnapshot());
- },
- enumerable: true,
- configurable: true
- });
- // NOTE: we use this method to get snapshot without creating @computed overhead
- ObjectNode.prototype.getSnapshot = function () {
- if (!this.isAlive)
- return this._snapshotUponDeath;
- return this._observableInstanceState === 2 /* CREATED */
- ? this._getActualSnapshot()
- : this._getCachedInitialSnapshot();
- };
- ObjectNode.prototype._getActualSnapshot = function () {
- return this.type.getSnapshot(this);
- };
- ObjectNode.prototype._getCachedInitialSnapshot = function () {
- if (!this._cachedInitialSnapshotCreated) {
- var type = this.type;
- var childNodes = this._childNodes;
- var snapshot = this._initialSnapshot;
- this._cachedInitialSnapshot = type.processInitialSnapshot(childNodes, snapshot);
- this._cachedInitialSnapshotCreated = true;
- }
- return this._cachedInitialSnapshot;
- };
- ObjectNode.prototype.isRunningAction = function () {
- if (this._isRunningAction)
- return true;
- if (this.isRoot)
- return false;
- return this.parent.isRunningAction();
- };
- ObjectNode.prototype.assertAlive = function (context) {
- var livelinessChecking = getLivelinessChecking();
- if (!this.isAlive && livelinessChecking !== "ignore") {
- var error = this._getAssertAliveError(context);
- switch (livelinessChecking) {
- case "error":
- throw fail$1(error);
- case "warn":
- warnError(error);
- }
- }
- };
- ObjectNode.prototype._getAssertAliveError = function (context) {
- var escapedPath = this.getEscapedPath(false) || this.pathUponDeath || "";
- var subpath = (context.subpath && escapeJsonPath(context.subpath)) || "";
- var actionContext = context.actionContext || getCurrentActionContext();
- // try to use a real action context if possible since it includes the action name
- if (actionContext && actionContext.type !== "action" && actionContext.parentActionEvent) {
- actionContext = actionContext.parentActionEvent;
- }
- var actionFullPath = "";
- if (actionContext && actionContext.name != null) {
- // try to use the context, and if it not available use the node one
- var actionPath = (actionContext && actionContext.context && getPath(actionContext.context)) ||
- escapedPath;
- actionFullPath = actionPath + "." + actionContext.name + "()";
- }
- return "You are trying to read or write to an object that is no longer part of a state tree. (Object type: '" + this.type.name + "', Path upon death: '" + escapedPath + "', Subpath: '" + subpath + "', Action: '" + actionFullPath + "'). Either detach nodes first, or don't use objects after removing / replacing them in the tree.";
- };
- ObjectNode.prototype.getChildNode = function (subpath) {
- this.assertAlive({
- subpath: subpath
- });
- this._autoUnbox = false;
- try {
- return this._observableInstanceState === 2 /* CREATED */
- ? this.type.getChildNode(this, subpath)
- : this._childNodes[subpath];
- }
- finally {
- this._autoUnbox = true;
- }
- };
- ObjectNode.prototype.getChildren = function () {
- this.assertAlive(EMPTY_OBJECT);
- this._autoUnbox = false;
- try {
- return this._observableInstanceState === 2 /* CREATED */
- ? this.type.getChildren(this)
- : convertChildNodesToArray(this._childNodes);
- }
- finally {
- this._autoUnbox = true;
- }
- };
- ObjectNode.prototype.getChildType = function (propertyName) {
- return this.type.getChildType(propertyName);
- };
- Object.defineProperty(ObjectNode.prototype, "isProtected", {
- get: function () {
- return this.root.isProtectionEnabled;
- },
- enumerable: true,
- configurable: true
- });
- ObjectNode.prototype.assertWritable = function (context) {
- this.assertAlive(context);
- if (!this.isRunningAction() && this.isProtected) {
- throw fail$1("Cannot modify '" + this + "', the object is protected and can only be modified by using an action.");
- }
- };
- ObjectNode.prototype.removeChild = function (subpath) {
- this.type.removeChild(this, subpath);
- };
- // bound on the constructor
- ObjectNode.prototype.unbox = function (childNode) {
- if (!childNode)
- return childNode;
- this.assertAlive({
- subpath: childNode.subpath || childNode.subpathUponDeath
- });
- return this._autoUnbox ? childNode.value : childNode;
- };
- ObjectNode.prototype.toString = function () {
- var path = (this.isAlive ? this.path : this.pathUponDeath) || "<root>";
- var identifier = this.identifier ? "(id: " + this.identifier + ")" : "";
- return this.type.name + "@" + path + identifier + (this.isAlive ? "" : " [dead]");
- };
- ObjectNode.prototype.finalizeCreation = function () {
- var _this = this;
- this.baseFinalizeCreation(function () {
- var e_2, _a;
- try {
- for (var _b = __values(_this.getChildren()), _c = _b.next(); !_c.done; _c = _b.next()) {
- var child = _c.value;
- child.finalizeCreation();
- }
- }
- catch (e_2_1) { e_2 = { error: e_2_1 }; }
- finally {
- try {
- if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
- }
- finally { if (e_2) throw e_2.error; }
- }
- _this.fireInternalHook(Hook.afterCreationFinalization);
- });
- };
- ObjectNode.prototype.detach = function () {
- if (!this.isAlive)
- throw fail$1("Error while detaching, node is not alive.");
- this.clearParent();
- };
- ObjectNode.prototype.preboot = function () {
- var self = this;
- this._applyPatches = createActionInvoker(this.storedValue, "@APPLY_PATCHES", function (patches) {
- patches.forEach(function (patch) {
- var parts = splitJsonPath(patch.path);
- var node = resolveNodeByPathParts(self, parts.slice(0, -1));
- node.applyPatchLocally(parts[parts.length - 1], patch);
- });
- });
- this._applySnapshot = createActionInvoker(this.storedValue, "@APPLY_SNAPSHOT", function (snapshot) {
- // if the snapshot is the same as the current one, avoid performing a reconcile
- if (snapshot === self.snapshot)
- return;
- // else, apply it by calling the type logic
- return self.type.applySnapshot(self, snapshot);
- });
- addHiddenFinalProp(this.storedValue, "$treenode", this);
- addHiddenFinalProp(this.storedValue, "toJSON", toJSON);
- };
- ObjectNode.prototype.die = function () {
- if (!this.isAlive || this.state === NodeLifeCycle.DETACHING)
- return;
- this.aboutToDie();
- this.finalizeDeath();
- };
- ObjectNode.prototype.aboutToDie = function () {
- if (this._observableInstanceState === 0 /* UNINITIALIZED */) {
- return;
- }
- this.getChildren().forEach(function (node) {
- node.aboutToDie();
- });
- // beforeDestroy should run before the disposers since else we could end up in a situation where
- // a disposer added with addDisposer at this stage (beforeDestroy) is actually never released
- this.baseAboutToDie();
- this._internalEventsEmit("dispose" /* Dispose */);
- this._internalEventsClear("dispose" /* Dispose */);
- };
- ObjectNode.prototype.finalizeDeath = function () {
- // invariant: not called directly but from "die"
- this.getChildren().forEach(function (node) {
- node.finalizeDeath();
- });
- this.root.identifierCache.notifyDied(this);
- // "kill" the computed prop and just store the last snapshot
- var snapshot = this.snapshot;
- this._snapshotUponDeath = snapshot;
- this._internalEventsClearAll();
- this.baseFinalizeDeath();
- };
- ObjectNode.prototype.onSnapshot = function (onChange) {
- this._addSnapshotReaction();
- return this._internalEventsRegister("snapshot" /* Snapshot */, onChange);
- };
- ObjectNode.prototype.emitSnapshot = function (snapshot) {
- this._internalEventsEmit("snapshot" /* Snapshot */, snapshot);
- };
- ObjectNode.prototype.onPatch = function (handler) {
- return this._internalEventsRegister("patch" /* Patch */, handler);
- };
- ObjectNode.prototype.emitPatch = function (basePatch, source) {
- if (this._internalEventsHasSubscribers("patch" /* Patch */)) {
- var localizedPatch = extend({}, basePatch, {
- path: source.path.substr(this.path.length) + "/" + basePatch.path // calculate the relative path of the patch
- });
- var _a = __read(splitPatch(localizedPatch), 2), patch = _a[0], reversePatch = _a[1];
- this._internalEventsEmit("patch" /* Patch */, patch, reversePatch);
- }
- if (this.parent)
- this.parent.emitPatch(basePatch, source);
- };
- ObjectNode.prototype.hasDisposer = function (disposer) {
- return this._internalEventsHas("dispose" /* Dispose */, disposer);
- };
- ObjectNode.prototype.addDisposer = function (disposer) {
- if (!this.hasDisposer(disposer)) {
- this._internalEventsRegister("dispose" /* Dispose */, disposer, true);
- return;
- }
- throw fail$1("cannot add a disposer when it is already registered for execution");
- };
- ObjectNode.prototype.removeDisposer = function (disposer) {
- if (!this._internalEventsHas("dispose" /* Dispose */, disposer)) {
- throw fail$1("cannot remove a disposer which was never registered for execution");
- }
- this._internalEventsUnregister("dispose" /* Dispose */, disposer);
- };
- ObjectNode.prototype.removeMiddleware = function (middleware) {
- if (this.middlewares) {
- var index = this.middlewares.indexOf(middleware);
- if (index >= 0) {
- this.middlewares.splice(index, 1);
- }
- }
- };
- ObjectNode.prototype.addMiddleWare = function (handler, includeHooks) {
- var _this = this;
- if (includeHooks === void 0) { includeHooks = true; }
- var middleware = { handler: handler, includeHooks: includeHooks };
- if (!this.middlewares)
- this.middlewares = [middleware];
- else
- this.middlewares.push(middleware);
- return function () {
- _this.removeMiddleware(middleware);
- };
- };
- ObjectNode.prototype.applyPatchLocally = function (subpath, patch) {
- this.assertWritable({
- subpath: subpath
- });
- this.createObservableInstanceIfNeeded();
- this.type.applyPatchLocally(this, subpath, patch);
- };
- ObjectNode.prototype._addSnapshotReaction = function () {
- var _this = this;
- if (!this._hasSnapshotReaction) {
- var snapshotDisposer = mobx.reaction(function () { return _this.snapshot; }, function (snapshot) { return _this.emitSnapshot(snapshot); }, snapshotReactionOptions);
- this.addDisposer(snapshotDisposer);
- this._hasSnapshotReaction = true;
- }
- };
- // we proxy the methods to avoid creating an EventHandlers instance when it is not needed
- ObjectNode.prototype._internalEventsHasSubscribers = function (event) {
- return !!this._internalEvents && this._internalEvents.hasSubscribers(event);
- };
- ObjectNode.prototype._internalEventsRegister = function (event, eventHandler, atTheBeginning) {
- if (atTheBeginning === void 0) { atTheBeginning = false; }
- if (!this._internalEvents) {
- this._internalEvents = new EventHandlers();
- }
- return this._internalEvents.register(event, eventHandler, atTheBeginning);
- };
- ObjectNode.prototype._internalEventsHas = function (event, eventHandler) {
- return !!this._internalEvents && this._internalEvents.has(event, eventHandler);
- };
- ObjectNode.prototype._internalEventsUnregister = function (event, eventHandler) {
- if (this._internalEvents) {
- this._internalEvents.unregister(event, eventHandler);
- }
- };
- ObjectNode.prototype._internalEventsEmit = function (event) {
- var _a;
- var args = [];
- for (var _i = 1; _i < arguments.length; _i++) {
- args[_i - 1] = arguments[_i];
- }
- if (this._internalEvents) {
- (_a = this._internalEvents).emit.apply(_a, __spread([event], args));
- }
- };
- ObjectNode.prototype._internalEventsClear = function (event) {
- if (this._internalEvents) {
- this._internalEvents.clear(event);
- }
- };
- ObjectNode.prototype._internalEventsClearAll = function () {
- if (this._internalEvents) {
- this._internalEvents.clearAll();
- }
- };
- __decorate([
- mobx.action
- ], ObjectNode.prototype, "createObservableInstanceIfNeeded", null);
- __decorate([
- mobx.computed
- ], ObjectNode.prototype, "snapshot", null);
- __decorate([
- mobx.action
- ], ObjectNode.prototype, "detach", null);
- __decorate([
- mobx.action
- ], ObjectNode.prototype, "die", null);
- return ObjectNode;
- }(BaseNode));
- /**
- * @internal
- * @hidden
- */
- var TypeFlags;
- (function (TypeFlags) {
- TypeFlags[TypeFlags["String"] = 1] = "String";
- TypeFlags[TypeFlags["Number"] = 2] = "Number";
- TypeFlags[TypeFlags["Boolean"] = 4] = "Boolean";
- TypeFlags[TypeFlags["Date"] = 8] = "Date";
- TypeFlags[TypeFlags["Literal"] = 16] = "Literal";
- TypeFlags[TypeFlags["Array"] = 32] = "Array";
- TypeFlags[TypeFlags["Map"] = 64] = "Map";
- TypeFlags[TypeFlags["Object"] = 128] = "Object";
- TypeFlags[TypeFlags["Frozen"] = 256] = "Frozen";
- TypeFlags[TypeFlags["Optional"] = 512] = "Optional";
- TypeFlags[TypeFlags["Reference"] = 1024] = "Reference";
- TypeFlags[TypeFlags["Identifier"] = 2048] = "Identifier";
- TypeFlags[TypeFlags["Late"] = 4096] = "Late";
- TypeFlags[TypeFlags["Refinement"] = 8192] = "Refinement";
- TypeFlags[TypeFlags["Union"] = 16384] = "Union";
- TypeFlags[TypeFlags["Null"] = 32768] = "Null";
- TypeFlags[TypeFlags["Undefined"] = 65536] = "Undefined";
- TypeFlags[TypeFlags["Integer"] = 131072] = "Integer";
- TypeFlags[TypeFlags["Custom"] = 262144] = "Custom";
- TypeFlags[TypeFlags["SnapshotProcessor"] = 524288] = "SnapshotProcessor";
- })(TypeFlags || (TypeFlags = {}));
- /**
- * @internal
- * @hidden
- */
- var cannotDetermineSubtype = "cannotDetermine";
- /**
- * A base type produces a MST node (Node in the state tree)
- *
- * @internal
- * @hidden
- */
- var BaseType = /** @class */ (function () {
- function BaseType(name) {
- this.isType = true;
- this.name = name;
- }
- BaseType.prototype.create = function (snapshot, environment) {
- typecheckInternal(this, snapshot);
- return this.instantiate(null, "", environment, snapshot).value;
- };
- BaseType.prototype.getSnapshot = function (node, applyPostProcess) {
- // istanbul ignore next
- throw fail$1("unimplemented method");
- };
- BaseType.prototype.isAssignableFrom = function (type) {
- return type === this;
- };
- BaseType.prototype.validate = function (value, context) {
- var node = getStateTreeNodeSafe(value);
- if (node) {
- var valueType = getType(value);
- return this.isAssignableFrom(valueType)
- ? typeCheckSuccess()
- : typeCheckFailure(context, value);
- // it is tempting to compare snapshots, but in that case we should always clone on assignments...
- }
- return this.isValidSnapshot(value, context);
- };
- BaseType.prototype.is = function (thing) {
- return this.validate(thing, [{ path: "", type: this }]).length === 0;
- };
- Object.defineProperty(BaseType.prototype, "Type", {
- get: function () {
- // istanbul ignore next
- throw fail$1("Factory.Type should not be actually called. It is just a Type signature that can be used at compile time with Typescript, by using `typeof type.Type`");
- },
- enumerable: true,
- configurable: true
- });
- Object.defineProperty(BaseType.prototype, "TypeWithoutSTN", {
- get: function () {
- // istanbul ignore next
- throw fail$1("Factory.TypeWithoutSTN should not be actually called. It is just a Type signature that can be used at compile time with Typescript, by using `typeof type.TypeWithoutSTN`");
- },
- enumerable: true,
- configurable: true
- });
- Object.defineProperty(BaseType.prototype, "SnapshotType", {
- get: function () {
- // istanbul ignore next
- throw fail$1("Factory.SnapshotType should not be actually called. It is just a Type signature that can be used at compile time with Typescript, by using `typeof type.SnapshotType`");
- },
- enumerable: true,
- configurable: true
- });
- Object.defineProperty(BaseType.prototype, "CreationType", {
- get: function () {
- // istanbul ignore next
- throw fail$1("Factory.CreationType should not be actually called. It is just a Type signature that can be used at compile time with Typescript, by using `typeof type.CreationType`");
- },
- enumerable: true,
- configurable: true
- });
- __decorate([
- mobx.action
- ], BaseType.prototype, "create", null);
- return BaseType;
- }());
- /**
- * A complex type produces a MST node (Node in the state tree)
- *
- * @internal
- * @hidden
- */
- var ComplexType = /** @class */ (function (_super) {
- __extends(ComplexType, _super);
- function ComplexType(name) {
- return _super.call(this, name) || this;
- }
- ComplexType.prototype.create = function (snapshot, environment) {
- if (snapshot === void 0) { snapshot = this.getDefaultSnapshot(); }
- return _super.prototype.create.call(this, snapshot, environment);
- };
- ComplexType.prototype.getValue = function (node) {
- node.createObservableInstanceIfNeeded();
- return node.storedValue;
- };
- ComplexType.prototype.tryToReconcileNode = function (current, newValue) {
- if (current.isDetaching)
- return false;
- if (current.snapshot === newValue) {
- // newValue is the current snapshot of the node, noop
- return true;
- }
- if (isStateTreeNode(newValue) && getStateTreeNode(newValue) === current) {
- // the current node is the same as the new one
- return true;
- }
- if (current.type === this &&
- isMutable(newValue) &&
- !isStateTreeNode(newValue) &&
- (!current.identifierAttribute ||
- current.identifier ===
- normalizeIdentifier(newValue[current.identifierAttribute]))) {
- // the newValue has no node, so can be treated like a snapshot
- // we can reconcile
- current.applySnapshot(newValue);
- return true;
- }
- return false;
- };
- ComplexType.prototype.reconcile = function (current, newValue, parent, subpath) {
- var nodeReconciled = this.tryToReconcileNode(current, newValue);
- if (nodeReconciled) {
- current.setParent(parent, subpath);
- return current;
- }
- // current node cannot be recycled in any way
- current.die(); // noop if detaching
- // attempt to reuse the new one
- if (isStateTreeNode(newValue) && this.isAssignableFrom(getType(newValue))) {
- // newValue is a Node as well, move it here..
- var newNode = getStateTreeNode(newValue);
- newNode.setParent(parent, subpath);
- return newNode;
- }
- // nothing to do, we have to create a new node
- return this.instantiate(parent, subpath, undefined, newValue);
- };
- ComplexType.prototype.getSubTypes = function () {
- return null;
- };
- __decorate([
- mobx.action
- ], ComplexType.prototype, "create", null);
- return ComplexType;
- }(BaseType));
- /**
- * @internal
- * @hidden
- */
- var SimpleType = /** @class */ (function (_super) {
- __extends(SimpleType, _super);
- function SimpleType() {
- return _super !== null && _super.apply(this, arguments) || this;
- }
- SimpleType.prototype.createNewInstance = function (snapshot) {
- return snapshot;
- };
- SimpleType.prototype.getValue = function (node) {
- // if we ever find a case where scalar nodes can be accessed without iterating through its parent
- // uncomment this to make sure the parent chain is created when this is accessed
- // if (node.parent) {
- // node.parent.createObservableInstanceIfNeeded()
- // }
- return node.storedValue;
- };
- SimpleType.prototype.getSnapshot = function (node) {
- return node.storedValue;
- };
- SimpleType.prototype.reconcile = function (current, newValue, parent, subpath) {
- // reconcile only if type and value are still the same, and only if the node is not detaching
- if (!current.isDetaching && current.type === this && current.storedValue === newValue) {
- return current;
- }
- var res = this.instantiate(parent, subpath, undefined, newValue);
- current.die(); // noop if detaching
- return res;
- };
- SimpleType.prototype.getSubTypes = function () {
- return null;
- };
- return SimpleType;
- }(BaseType));
- /**
- * Returns if a given value represents a type.
- *
- * @param value Value to check.
- * @returns `true` if the value is a type.
- */
- function isType(value) {
- return typeof value === "object" && value && value.isType === true;
- }
- /**
- * @internal
- * @hidden
- */
- function assertIsType(type, argNumber) {
- assertArg(type, isType, "mobx-state-tree type", argNumber);
- }
- var runningActions = new Map();
- /**
- * Note: Consider migrating to `createActionTrackingMiddleware2`, it is easier to use.
- *
- * Convenience utility to create action based middleware that supports async processes more easily.
- * All hooks are called for both synchronous and asynchronous actions. Except that either `onSuccess` or `onFail` is called
- *
- * The create middleware tracks the process of an action (assuming it passes the `filter`).
- * `onResume` can return any value, which will be passed as second argument to any other hook. This makes it possible to keep state during a process.
- *
- * See the `atomic` middleware for an example
- *
- * @param hooks
- * @returns
- */
- function createActionTrackingMiddleware(hooks) {
- return function actionTrackingMiddleware(call, next, abort) {
- switch (call.type) {
- case "action": {
- if (!hooks.filter || hooks.filter(call) === true) {
- var context = hooks.onStart(call);
- hooks.onResume(call, context);
- runningActions.set(call.id, {
- call: call,
- context: context,
- async: false
- });
- try {
- var res = next(call);
- hooks.onSuspend(call, context);
- if (runningActions.get(call.id).async === false) {
- runningActions.delete(call.id);
- hooks.onSuccess(call, context, res);
- }
- return res;
- }
- catch (e) {
- runningActions.delete(call.id);
- hooks.onFail(call, context, e);
- throw e;
- }
- }
- else {
- return next(call);
- }
- }
- case "flow_spawn": {
- var root = runningActions.get(call.rootId);
- root.async = true;
- return next(call);
- }
- case "flow_resume":
- case "flow_resume_error": {
- var root = runningActions.get(call.rootId);
- hooks.onResume(call, root.context);
- try {
- return next(call);
- }
- finally {
- hooks.onSuspend(call, root.context);
- }
- }
- case "flow_throw": {
- var root = runningActions.get(call.rootId);
- runningActions.delete(call.rootId);
- hooks.onFail(call, root.context, call.args[0]);
- return next(call);
- }
- case "flow_return": {
- var root = runningActions.get(call.rootId);
- runningActions.delete(call.rootId);
- hooks.onSuccess(call, root.context, call.args[0]);
- return next(call);
- }
- }
- };
- }
- var RunningAction = /** @class */ (function () {
- function RunningAction(hooks, call) {
- this.hooks = hooks;
- this.call = call;
- this.flowsPending = 0;
- this.running = true;
- if (hooks) {
- hooks.onStart(call);
- }
- }
- RunningAction.prototype.finish = function (error) {
- if (this.running) {
- this.running = false;
- if (this.hooks) {
- this.hooks.onFinish(this.call, error);
- }
- }
- };
- RunningAction.prototype.incFlowsPending = function () {
- this.flowsPending++;
- };
- RunningAction.prototype.decFlowsPending = function () {
- this.flowsPending--;
- };
- Object.defineProperty(RunningAction.prototype, "hasFlowsPending", {
- get: function () {
- return this.flowsPending > 0;
- },
- enumerable: true,
- configurable: true
- });
- return RunningAction;
- }());
- /**
- * Convenience utility to create action based middleware that supports async processes more easily.
- * The flow is like this:
- * - for each action: if filter passes -> `onStart` -> (inner actions recursively) -> `onFinish`
- *
- * Example: if we had an action `a` that called inside an action `b1`, then `b2` the flow would be:
- * - `filter(a)`
- * - `onStart(a)`
- * - `filter(b1)`
- * - `onStart(b1)`
- * - `onFinish(b1)`
- * - `filter(b2)`
- * - `onStart(b2)`
- * - `onFinish(b2)`
- * - `onFinish(a)`
- *
- * The flow is the same no matter if the actions are sync or async.
- *
- * See the `atomic` middleware for an example
- *
- * @param hooks
- * @returns
- */
- function createActionTrackingMiddleware2(middlewareHooks) {
- var runningActions = new WeakMap();
- return function actionTrackingMiddleware(call, next) {
- // find parentRunningAction
- var parentRunningAction = call.parentActionEvent
- ? runningActions.get(call.parentActionEvent)
- : undefined;
- if (call.type === "action") {
- var newCall = __assign(__assign({}, call), {
- // make a shallow copy of the parent action env
- env: parentRunningAction && parentRunningAction.call.env, parentCall: parentRunningAction && parentRunningAction.call });
- var passesFilter = !middlewareHooks.filter || middlewareHooks.filter(newCall);
- var hooks = passesFilter ? middlewareHooks : undefined;
- var runningAction = new RunningAction(hooks, newCall);
- runningActions.set(call, runningAction);
- var res = void 0;
- try {
- res = next(call);
- }
- catch (e) {
- runningAction.finish(e);
- throw e;
- }
- if (!runningAction.hasFlowsPending) {
- // sync action finished
- runningAction.finish();
- }
- return res;
- }
- else {
- if (!parentRunningAction) {
- return next(call);
- }
- switch (call.type) {
- case "flow_spawn": {
- parentRunningAction.incFlowsPending();
- return next(call);
- }
- case "flow_resume":
- case "flow_resume_error": {
- return next(call);
- }
- case "flow_throw": {
- var error = call.args[0];
- try {
- return next(call);
- }
- finally {
- parentRunningAction.decFlowsPending();
- if (!parentRunningAction.hasFlowsPending) {
- parentRunningAction.finish(error);
- }
- }
- }
- case "flow_return": {
- try {
- return next(call);
- }
- finally {
- parentRunningAction.decFlowsPending();
- if (!parentRunningAction.hasFlowsPending) {
- parentRunningAction.finish();
- }
- }
- }
- }
- }
- };
- }
- function serializeArgument(node, actionName, index, arg) {
- if (arg instanceof Date)
- return { $MST_DATE: arg.getTime() };
- if (isPrimitive(arg))
- return arg;
- // We should not serialize MST nodes, even if we can, because we don't know if the receiving party can handle a raw snapshot instead of an
- // MST type instance. So if one wants to serialize a MST node that was pass in, either explitly pass: 1: an id, 2: a (relative) path, 3: a snapshot
- if (isStateTreeNode(arg))
- return serializeTheUnserializable("[MSTNode: " + getType(arg).name + "]");
- if (typeof arg === "function")
- return serializeTheUnserializable("[function]");
- if (typeof arg === "object" && !isPlainObject(arg) && !isArray(arg))
- return serializeTheUnserializable("[object " + ((arg && arg.constructor && arg.constructor.name) ||
- "Complex Object") + "]");
- try {
- // Check if serializable, cycle free etc...
- // MWE: there must be a better way....
- JSON.stringify(arg); // or throws
- return arg;
- }
- catch (e) {
- return serializeTheUnserializable("" + e);
- }
- }
- function deserializeArgument(adm, value) {
- if (value && typeof value === "object" && "$MST_DATE" in value)
- return new Date(value["$MST_DATE"]);
- return value;
- }
- function serializeTheUnserializable(baseType) {
- return {
- $MST_UNSERIALIZABLE: true,
- type: baseType
- };
- }
- /**
- * Applies an action or a series of actions in a single MobX transaction.
- * Does not return any value
- * Takes an action description as produced by the `onAction` middleware.
- *
- * @param target
- * @param actions
- */
- function applyAction(target, actions) {
- // check all arguments
- assertIsStateTreeNode(target, 1);
- assertArg(actions, function (a) { return typeof a === "object"; }, "object or array", 2);
- mobx.runInAction(function () {
- asArray(actions).forEach(function (action) { return baseApplyAction(target, action); });
- });
- }
- function baseApplyAction(target, action) {
- var resolvedTarget = tryResolve(target, action.path || "");
- if (!resolvedTarget)
- throw fail$1("Invalid action path: " + (action.path || ""));
- var node = getStateTreeNode(resolvedTarget);
- // Reserved functions
- if (action.name === "@APPLY_PATCHES") {
- return applyPatch.call(null, resolvedTarget, action.args[0]);
- }
- if (action.name === "@APPLY_SNAPSHOT") {
- return applySnapshot.call(null, resolvedTarget, action.args[0]);
- }
- if (!(typeof resolvedTarget[action.name] === "function"))
- throw fail$1("Action '" + action.name + "' does not exist in '" + node.path + "'");
- return resolvedTarget[action.name].apply(resolvedTarget, action.args ? action.args.map(function (v) { return deserializeArgument(node, v); }) : []);
- }
- /**
- * Small abstraction around `onAction` and `applyAction`, attaches an action listener to a tree and records all the actions emitted.
- * Returns an recorder object with the following signature:
- *
- * Example:
- * ```ts
- * export interface IActionRecorder {
- * // the recorded actions
- * actions: ISerializedActionCall[]
- * // true if currently recording
- * recording: boolean
- * // stop recording actions
- * stop(): void
- * // resume recording actions
- * resume(): void
- * // apply all the recorded actions on the given object
- * replay(target: IAnyStateTreeNode): void
- * }
- * ```
- *
- * The optional filter function allows to skip recording certain actions.
- *
- * @param subject
- * @returns
- */
- function recordActions(subject, filter) {
- // check all arguments
- assertIsStateTreeNode(subject, 1);
- var actions = [];
- var listener = function (call) {
- var recordThis = filter ? filter(call, getRunningActionContext()) : true;
- if (recordThis) {
- actions.push(call);
- }
- };
- var disposer;
- var recorder = {
- actions: actions,
- get recording() {
- return !!disposer;
- },
- stop: function () {
- if (disposer) {
- disposer();
- disposer = undefined;
- }
- },
- resume: function () {
- if (disposer)
- return;
- disposer = onAction(subject, listener);
- },
- replay: function (target) {
- applyAction(target, actions);
- }
- };
- recorder.resume();
- return recorder;
- }
- /**
- * Registers a function that will be invoked for each action that is called on the provided model instance, or to any of its children.
- * See [actions](https://github.com/mobxjs/mobx-state-tree#actions) for more details. onAction events are emitted only for the outermost called action in the stack.
- * Action can also be intercepted by middleware using addMiddleware to change the function call before it will be run.
- *
- * Not all action arguments might be serializable. For unserializable arguments, a struct like `{ $MST_UNSERIALIZABLE: true, type: "someType" }` will be generated.
- * MST Nodes are considered non-serializable as well (they could be serialized as there snapshot, but it is uncertain whether an replaying party will be able to handle such a non-instantiated snapshot).
- * Rather, when using `onAction` middleware, one should consider in passing arguments which are 1: an id, 2: a (relative) path, or 3: a snapshot. Instead of a real MST node.
- *
- * Example:
- * ```ts
- * const Todo = types.model({
- * task: types.string
- * })
- *
- * const TodoStore = types.model({
- * todos: types.array(Todo)
- * }).actions(self => ({
- * add(todo) {
- * self.todos.push(todo);
- * }
- * }))
- *
- * const s = TodoStore.create({ todos: [] })
- *
- * let disposer = onAction(s, (call) => {
- * console.log(call);
- * })
- *
- * s.add({ task: "Grab a coffee" })
- * // Logs: { name: "add", path: "", args: [{ task: "Grab a coffee" }] }
- * ```
- *
- * @param target
- * @param listener
- * @param attachAfter (default false) fires the listener *after* the action has executed instead of before.
- * @returns
- */
- function onAction(target, listener, attachAfter) {
- if (attachAfter === void 0) { attachAfter = false; }
- // check all arguments
- assertIsStateTreeNode(target, 1);
- if (devMode()) {
- if (!isRoot(target))
- warnError("Warning: Attaching onAction listeners to non root nodes is dangerous: No events will be emitted for actions initiated higher up in the tree.");
- if (!isProtected(target))
- warnError("Warning: Attaching onAction listeners to non protected nodes is dangerous: No events will be emitted for direct modifications without action.");
- }
- return addMiddleware(target, function handler(rawCall, next) {
- if (rawCall.type === "action" && rawCall.id === rawCall.rootId) {
- var sourceNode_1 = getStateTreeNode(rawCall.context);
- var info = {
- name: rawCall.name,
- path: getRelativePathBetweenNodes(getStateTreeNode(target), sourceNode_1),
- args: rawCall.args.map(function (arg, index) {
- return serializeArgument(sourceNode_1, rawCall.name, index, arg);
- })
- };
- if (attachAfter) {
- var res = next(rawCall);
- listener(info);
- return res;
- }
- else {
- listener(info);
- return next(rawCall);
- }
- }
- else {
- return next(rawCall);
- }
- });
- }
- var nextActionId = 1;
- var currentActionContext;
- /**
- * @internal
- * @hidden
- */
- function getCurrentActionContext() {
- return currentActionContext;
- }
- /**
- * @internal
- * @hidden
- */
- function getNextActionId() {
- return nextActionId++;
- }
- // TODO: optimize away entire action context if there is no middleware in tree?
- /**
- * @internal
- * @hidden
- */
- function runWithActionContext(context, fn) {
- var node = getStateTreeNode(context.context);
- if (context.type === "action") {
- node.assertAlive({
- actionContext: context
- });
- }
- var baseIsRunningAction = node._isRunningAction;
- node._isRunningAction = true;
- var previousContext = currentActionContext;
- currentActionContext = context;
- try {
- return runMiddleWares(node, context, fn);
- }
- finally {
- currentActionContext = previousContext;
- node._isRunningAction = baseIsRunningAction;
- }
- }
- /**
- * @internal
- * @hidden
- */
- function getParentActionContext(parentContext) {
- if (!parentContext)
- return undefined;
- if (parentContext.type === "action")
- return parentContext;
- return parentContext.parentActionEvent;
- }
- /**
- * @internal
- * @hidden
- */
- function createActionInvoker(target, name, fn) {
- var res = function () {
- var id = getNextActionId();
- var parentContext = currentActionContext;
- var parentActionContext = getParentActionContext(parentContext);
- return runWithActionContext({
- type: "action",
- name: name,
- id: id,
- args: argsToArray(arguments),
- context: target,
- tree: getRoot(target),
- rootId: parentContext ? parentContext.rootId : id,
- parentId: parentContext ? parentContext.id : 0,
- allParentIds: parentContext
- ? __spread(parentContext.allParentIds, [parentContext.id]) : [],
- parentEvent: parentContext,
- parentActionEvent: parentActionContext
- }, fn);
- };
- res._isMSTAction = true;
- return res;
- }
- /**
- * Middleware can be used to intercept any action is invoked on the subtree where it is attached.
- * If a tree is protected (by default), this means that any mutation of the tree will pass through your middleware.
- *
- * For more details, see the [middleware docs](../middleware.md)
- *
- * @param target Node to apply the middleware to.
- * @param middleware Middleware to apply.
- * @returns A callable function to dispose the middleware.
- */
- function addMiddleware(target, handler, includeHooks) {
- if (includeHooks === void 0) { includeHooks = true; }
- var node = getStateTreeNode(target);
- if (devMode()) {
- if (!node.isProtectionEnabled) {
- warnError("It is recommended to protect the state tree before attaching action middleware, as otherwise it cannot be guaranteed that all changes are passed through middleware. See `protect`");
- }
- }
- return node.addMiddleWare(handler, includeHooks);
- }
- /**
- * Binds middleware to a specific action.
- *
- * Example:
- * ```ts
- * type.actions(self => {
- * function takeA____() {
- * self.toilet.donate()
- * self.wipe()
- * self.wipe()
- * self.toilet.flush()
- * }
- * return {
- * takeA____: decorate(atomic, takeA____)
- * }
- * })
- * ```
- *
- * @param handler
- * @param fn
- * @param includeHooks
- * @returns The original function
- */
- function decorate(handler, fn, includeHooks) {
- if (includeHooks === void 0) { includeHooks = true; }
- var middleware = { handler: handler, includeHooks: includeHooks };
- fn.$mst_middleware = fn.$mst_middleware || [];
- fn.$mst_middleware.push(middleware);
- return fn;
- }
- var CollectedMiddlewares = /** @class */ (function () {
- function CollectedMiddlewares(node, fn) {
- this.arrayIndex = 0;
- this.inArrayIndex = 0;
- this.middlewares = [];
- // we just push middleware arrays into an array of arrays to avoid making copies
- if (fn.$mst_middleware) {
- this.middlewares.push(fn.$mst_middleware);
- }
- var n = node;
- // Find all middlewares. Optimization: cache this?
- while (n) {
- if (n.middlewares)
- this.middlewares.push(n.middlewares);
- n = n.parent;
- }
- }
- Object.defineProperty(CollectedMiddlewares.prototype, "isEmpty", {
- get: function () {
- return this.middlewares.length <= 0;
- },
- enumerable: true,
- configurable: true
- });
- CollectedMiddlewares.prototype.getNextMiddleware = function () {
- var array = this.middlewares[this.arrayIndex];
- if (!array)
- return undefined;
- var item = array[this.inArrayIndex++];
- if (!item) {
- this.arrayIndex++;
- this.inArrayIndex = 0;
- return this.getNextMiddleware();
- }
- return item;
- };
- return CollectedMiddlewares;
- }());
- function runMiddleWares(node, baseCall, originalFn) {
- var middlewares = new CollectedMiddlewares(node, originalFn);
- // Short circuit
- if (middlewares.isEmpty)
- return mobx.action(originalFn).apply(null, baseCall.args);
- var result = null;
- function runNextMiddleware(call) {
- var middleware = middlewares.getNextMiddleware();
- var handler = middleware && middleware.handler;
- if (!handler) {
- return mobx.action(originalFn).apply(null, call.args);
- }
- // skip hooks if asked to
- if (!middleware.includeHooks && Hook[call.name]) {
- return runNextMiddleware(call);
- }
- var nextInvoked = false;
- function next(call2, callback) {
- nextInvoked = true;
- // the result can contain
- // - the non manipulated return value from an action
- // - the non manipulated abort value
- // - one of the above but manipulated through the callback function
- result = runNextMiddleware(call2);
- if (callback) {
- result = callback(result);
- }
- }
- var abortInvoked = false;
- function abort(value) {
- abortInvoked = true;
- // overwrite the result
- // can be manipulated through middlewares earlier in the queue using the callback fn
- result = value;
- }
- handler(call, next, abort);
- if (devMode()) {
- if (!nextInvoked && !abortInvoked) {
- var node2 = getStateTreeNode(call.tree);
- throw fail$1("Neither the next() nor the abort() callback within the middleware " + handler.name + " for the action: \"" + call.name + "\" on the node: " + node2.type.name + " was invoked.");
- }
- else if (nextInvoked && abortInvoked) {
- var node2 = getStateTreeNode(call.tree);
- throw fail$1("The next() and abort() callback within the middleware " + handler.name + " for the action: \"" + call.name + "\" on the node: " + node2.type.name + " were invoked.");
- }
- }
- return result;
- }
- return runNextMiddleware(baseCall);
- }
- /**
- * Returns the currently executing MST action context, or undefined if none.
- */
- function getRunningActionContext() {
- var current = getCurrentActionContext();
- while (current && current.type !== "action") {
- current = current.parentActionEvent;
- }
- return current;
- }
- function _isActionContextThisOrChildOf(actionContext, sameOrParent, includeSame) {
- var parentId = typeof sameOrParent === "number" ? sameOrParent : sameOrParent.id;
- var current = includeSame
- ? actionContext
- : actionContext.parentActionEvent;
- while (current) {
- if (current.id === parentId) {
- return true;
- }
- current = current.parentActionEvent;
- }
- return false;
- }
- /**
- * Returns if the given action context is a parent of this action context.
- */
- function isActionContextChildOf(actionContext, parent) {
- return _isActionContextThisOrChildOf(actionContext, parent, false);
- }
- /**
- * Returns if the given action context is this or a parent of this action context.
- */
- function isActionContextThisOrChildOf(actionContext, parentOrThis) {
- return _isActionContextThisOrChildOf(actionContext, parentOrThis, true);
- }
- function safeStringify(value) {
- try {
- return JSON.stringify(value);
- }
- catch (e) {
- // istanbul ignore next
- return "<Unserializable: " + e + ">";
- }
- }
- /**
- * @internal
- * @hidden
- */
- function prettyPrintValue(value) {
- return typeof value === "function"
- ? "<function" + (value.name ? " " + value.name : "") + ">"
- : isStateTreeNode(value)
- ? "<" + value + ">"
- : "`" + safeStringify(value) + "`";
- }
- function shortenPrintValue(valueInString) {
- return valueInString.length < 280
- ? valueInString
- : valueInString.substring(0, 272) + "......" + valueInString.substring(valueInString.length - 8);
- }
- function toErrorString(error) {
- var value = error.value;
- var type = error.context[error.context.length - 1].type;
- var fullPath = error.context
- .map(function (_a) {
- var path = _a.path;
- return path;
- })
- .filter(function (path) { return path.length > 0; })
- .join("/");
- var pathPrefix = fullPath.length > 0 ? "at path \"/" + fullPath + "\" " : "";
- var currentTypename = isStateTreeNode(value)
- ? "value of type " + getStateTreeNode(value).type.name + ":"
- : isPrimitive(value)
- ? "value"
- : "snapshot";
- var isSnapshotCompatible = type && isStateTreeNode(value) && type.is(getStateTreeNode(value).snapshot);
- return ("" + pathPrefix + currentTypename + " " + prettyPrintValue(value) + " is not assignable " + (type ? "to type: `" + type.name + "`" : "") +
- (error.message ? " (" + error.message + ")" : "") +
- (type
- ? isPrimitiveType(type) || isPrimitive(value)
- ? "."
- : ", expected an instance of `" + type.name + "` or a snapshot like `" + type.describe() + "` instead." +
- (isSnapshotCompatible
- ? " (Note that a snapshot of the provided value is compatible with the targeted type)"
- : "")
- : "."));
- }
- /**
- * @internal
- * @hidden
- */
- function getContextForPath(context, path, type) {
- return context.concat([{ path: path, type: type }]);
- }
- /**
- * @internal
- * @hidden
- */
- function typeCheckSuccess() {
- return EMPTY_ARRAY;
- }
- /**
- * @internal
- * @hidden
- */
- function typeCheckFailure(context, value, message) {
- return [{ context: context, value: value, message: message }];
- }
- /**
- * @internal
- * @hidden
- */
- function flattenTypeErrors(errors) {
- return errors.reduce(function (a, i) { return a.concat(i); }, []);
- }
- // TODO; doublecheck: typecheck should only needed to be invoked from: type.create and array / map / value.property will change
- /**
- * @internal
- * @hidden
- */
- function typecheckInternal(type, value) {
- // runs typeChecking if it is in dev-mode or through a process.env.ENABLE_TYPE_CHECK flag
- if (isTypeCheckingEnabled()) {
- typecheck(type, value);
- }
- }
- /**
- * Run's the typechecker for the given type on the given value, which can be a snapshot or an instance.
- * Throws if the given value is not according the provided type specification.
- * Use this if you need typechecks even in a production build (by default all automatic runtime type checks will be skipped in production builds)
- *
- * @param type Type to check against.
- * @param value Value to be checked, either a snapshot or an instance.
- */
- function typecheck(type, value) {
- var errors = type.validate(value, [{ path: "", type: type }]);
- if (errors.length > 0) {
- throw fail$1(validationErrorsToString(type, value, errors));
- }
- }
- function validationErrorsToString(type, value, errors) {
- if (errors.length === 0) {
- return undefined;
- }
- return ("Error while converting " + shortenPrintValue(prettyPrintValue(value)) + " to `" + type.name + "`:\n\n " + errors.map(toErrorString).join("\n "));
- }
- var identifierCacheId = 0;
- /**
- * @internal
- * @hidden
- */
- var IdentifierCache = /** @class */ (function () {
- function IdentifierCache() {
- this.cacheId = identifierCacheId++;
- // n.b. in cache all identifiers are normalized to strings
- this.cache = mobx.observable.map();
- // last time the cache (array) for a given time changed
- // n.b. it is not really the time, but just an integer that gets increased after each modification to the array
- this.lastCacheModificationPerId = mobx.observable.map();
- }
- IdentifierCache.prototype.updateLastCacheModificationPerId = function (identifier) {
- var lcm = this.lastCacheModificationPerId.get(identifier);
- // we start at 1 since 0 means no update since cache creation
- this.lastCacheModificationPerId.set(identifier, lcm === undefined ? 1 : lcm + 1);
- };
- IdentifierCache.prototype.getLastCacheModificationPerId = function (identifier) {
- var modificationId = this.lastCacheModificationPerId.get(identifier) || 0;
- return this.cacheId + "-" + modificationId;
- };
- IdentifierCache.prototype.addNodeToCache = function (node, lastCacheUpdate) {
- if (lastCacheUpdate === void 0) { lastCacheUpdate = true; }
- if (node.identifierAttribute) {
- var identifier = node.identifier;
- if (!this.cache.has(identifier)) {
- this.cache.set(identifier, mobx.observable.array([], mobxShallow));
- }
- var set = this.cache.get(identifier);
- if (set.indexOf(node) !== -1)
- throw fail$1("Already registered");
- set.push(node);
- if (lastCacheUpdate) {
- this.updateLastCacheModificationPerId(identifier);
- }
- }
- };
- IdentifierCache.prototype.mergeCache = function (node) {
- var _this = this;
- mobx.values(node.identifierCache.cache).forEach(function (nodes) {
- return nodes.forEach(function (child) {
- _this.addNodeToCache(child);
- });
- });
- };
- IdentifierCache.prototype.notifyDied = function (node) {
- if (node.identifierAttribute) {
- var id = node.identifier;
- var set = this.cache.get(id);
- if (set) {
- set.remove(node);
- // remove empty sets from cache
- if (!set.length) {
- this.cache.delete(id);
- }
- this.updateLastCacheModificationPerId(node.identifier);
- }
- }
- };
- IdentifierCache.prototype.splitCache = function (node) {
- var _this = this;
- var res = new IdentifierCache();
- var basePath = node.path;
- mobx.entries(this.cache).forEach(function (_a) {
- var _b = __read(_a, 2), id = _b[0], nodes = _b[1];
- var modified = false;
- for (var i = nodes.length - 1; i >= 0; i--) {
- if (nodes[i].path.indexOf(basePath) === 0) {
- res.addNodeToCache(nodes[i], false); // no need to update lastUpdated since it is a whole new cache
- nodes.splice(i, 1);
- modified = true;
- }
- }
- if (modified) {
- _this.updateLastCacheModificationPerId(id);
- }
- });
- return res;
- };
- IdentifierCache.prototype.has = function (type, identifier) {
- var set = this.cache.get(identifier);
- if (!set)
- return false;
- return set.some(function (candidate) { return type.isAssignableFrom(candidate.type); });
- };
- IdentifierCache.prototype.resolve = function (type, identifier) {
- var set = this.cache.get(identifier);
- if (!set)
- return null;
- var matches = set.filter(function (candidate) { return type.isAssignableFrom(candidate.type); });
- switch (matches.length) {
- case 0:
- return null;
- case 1:
- return matches[0];
- default:
- throw fail$1("Cannot resolve a reference to type '" + type.name + "' with id: '" + identifier + "' unambigously, there are multiple candidates: " + matches
- .map(function (n) { return n.path; })
- .join(", "));
- }
- };
- return IdentifierCache;
- }());
- /**
- * @internal
- * @hidden
- */
- function createObjectNode(type, parent, subpath, environment, initialValue) {
- var existingNode = getStateTreeNodeSafe(initialValue);
- if (existingNode) {
- if (existingNode.parent) {
- // istanbul ignore next
- throw fail$1("Cannot add an object to a state tree if it is already part of the same or another state tree. Tried to assign an object to '" + (parent ? parent.path : "") + "/" + subpath + "', but it lives already at '" + existingNode.path + "'");
- }
- if (parent) {
- existingNode.setParent(parent, subpath);
- }
- // else it already has no parent since it is a pre-requisite
- return existingNode;
- }
- // not a node, a snapshot
- return new ObjectNode(type, parent, subpath, environment, initialValue);
- }
- /**
- * @internal
- * @hidden
- */
- function createScalarNode(type, parent, subpath, environment, initialValue) {
- return new ScalarNode(type, parent, subpath, environment, initialValue);
- }
- /**
- * @internal
- * @hidden
- */
- function isNode(value) {
- return value instanceof ScalarNode || value instanceof ObjectNode;
- }
- /**
- * @internal
- * @hidden
- */
- var NodeLifeCycle;
- (function (NodeLifeCycle) {
- NodeLifeCycle[NodeLifeCycle["INITIALIZING"] = 0] = "INITIALIZING";
- NodeLifeCycle[NodeLifeCycle["CREATED"] = 1] = "CREATED";
- NodeLifeCycle[NodeLifeCycle["FINALIZED"] = 2] = "FINALIZED";
- NodeLifeCycle[NodeLifeCycle["DETACHING"] = 3] = "DETACHING";
- NodeLifeCycle[NodeLifeCycle["DEAD"] = 4] = "DEAD"; // no coming back from this one
- })(NodeLifeCycle || (NodeLifeCycle = {}));
- /**
- * Returns true if the given value is a node in a state tree.
- * More precisely, that is, if the value is an instance of a
- * `types.model`, `types.array` or `types.map`.
- *
- * @param value
- * @returns true if the value is a state tree node.
- */
- function isStateTreeNode(value) {
- return !!(value && value.$treenode);
- }
- /**
- * @internal
- * @hidden
- */
- function assertIsStateTreeNode(value, argNumber) {
- assertArg(value, isStateTreeNode, "mobx-state-tree node", argNumber);
- }
- /**
- * @internal
- * @hidden
- */
- function getStateTreeNode(value) {
- if (!isStateTreeNode(value)) {
- // istanbul ignore next
- throw fail$1("Value " + value + " is no MST Node");
- }
- return value.$treenode;
- }
- /**
- * @internal
- * @hidden
- */
- function getStateTreeNodeSafe(value) {
- return (value && value.$treenode) || null;
- }
- /**
- * @internal
- * @hidden
- */
- function toJSON() {
- return getStateTreeNode(this).snapshot;
- }
- var doubleDot = function (_) { return ".."; };
- /**
- * @internal
- * @hidden
- */
- function getRelativePathBetweenNodes(base, target) {
- // PRE condition target is (a child of) base!
- if (base.root !== target.root) {
- throw fail$1("Cannot calculate relative path: objects '" + base + "' and '" + target + "' are not part of the same object tree");
- }
- var baseParts = splitJsonPath(base.path);
- var targetParts = splitJsonPath(target.path);
- var common = 0;
- for (; common < baseParts.length; common++) {
- if (baseParts[common] !== targetParts[common])
- break;
- }
- // TODO: assert that no targetParts paths are "..", "." or ""!
- return (baseParts
- .slice(common)
- .map(doubleDot)
- .join("/") + joinJsonPath(targetParts.slice(common)));
- }
- /**
- * @internal
- * @hidden
- */
- function resolveNodeByPath(base, path, failIfResolveFails) {
- if (failIfResolveFails === void 0) { failIfResolveFails = true; }
- return resolveNodeByPathParts(base, splitJsonPath(path), failIfResolveFails);
- }
- /**
- * @internal
- * @hidden
- */
- function resolveNodeByPathParts(base, pathParts, failIfResolveFails) {
- if (failIfResolveFails === void 0) { failIfResolveFails = true; }
- var current = base;
- for (var i = 0; i < pathParts.length; i++) {
- var part = pathParts[i];
- if (part === "..") {
- current = current.parent;
- if (current)
- continue; // not everything has a parent
- }
- else if (part === ".") {
- continue;
- }
- else if (current) {
- if (current instanceof ScalarNode) {
- // check if the value of a scalar resolves to a state tree node (e.g. references)
- // then we can continue resolving...
- try {
- var value = current.value;
- if (isStateTreeNode(value)) {
- current = getStateTreeNode(value);
- // fall through
- }
- }
- catch (e) {
- if (!failIfResolveFails) {
- return undefined;
- }
- throw e;
- }
- }
- if (current instanceof ObjectNode) {
- var subType = current.getChildType(part);
- if (subType) {
- current = current.getChildNode(part);
- if (current)
- continue;
- }
- }
- }
- if (failIfResolveFails)
- throw fail$1("Could not resolve '" + part + "' in path '" + (joinJsonPath(pathParts.slice(0, i)) ||
- "/") + "' while resolving '" + joinJsonPath(pathParts) + "'");
- else
- return undefined;
- }
- return current;
- }
- /**
- * @internal
- * @hidden
- */
- function convertChildNodesToArray(childNodes) {
- if (!childNodes)
- return EMPTY_ARRAY;
- var keys = Object.keys(childNodes);
- if (!keys.length)
- return EMPTY_ARRAY;
- var result = new Array(keys.length);
- keys.forEach(function (key, index) {
- result[index] = childNodes[key];
- });
- return result;
- }
- // based on: https://github.com/mobxjs/mobx-utils/blob/master/src/async-action.ts
- /*
- All contents of this file are deprecated.
- The term `process` has been replaced with `flow` to avoid conflicts with the
- global `process` object.
- Refer to `flow.ts` for any further changes to this implementation.
- */
- var DEPRECATION_MESSAGE = "See https://github.com/mobxjs/mobx-state-tree/issues/399 for more information. " +
- "Note that the middleware event types starting with `process` now start with `flow`.";
- /**
- * @hidden
- *
- * @deprecated has been renamed to `flow()`.
- * See https://github.com/mobxjs/mobx-state-tree/issues/399 for more information.
- * Note that the middleware event types starting with `process` now start with `flow`.
- *
- * @returns {Promise}
- */
- function process$1(asyncAction) {
- deprecated("process", "`process()` has been renamed to `flow()`. " + DEPRECATION_MESSAGE);
- return flow(asyncAction);
- }
- /**
- * @internal
- * @hidden
- */
- var EMPTY_ARRAY = Object.freeze([]);
- /**
- * @internal
- * @hidden
- */
- var EMPTY_OBJECT = Object.freeze({});
- /**
- * @internal
- * @hidden
- */
- var mobxShallow = typeof mobx.$mobx === "string" ? { deep: false } : { deep: false, proxy: false };
- Object.freeze(mobxShallow);
- /**
- * @internal
- * @hidden
- */
- function fail$1(message) {
- if (message === void 0) { message = "Illegal state"; }
- return new Error("[mobx-state-tree] " + message);
- }
- /**
- * @internal
- * @hidden
- */
- function identity(_) {
- return _;
- }
- /**
- * pollyfill (for IE) suggested in MDN:
- * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger
- * @internal
- * @hidden
- */
- var isInteger = Number.isInteger ||
- function (value) {
- return typeof value === "number" && isFinite(value) && Math.floor(value) === value;
- };
- /**
- * @internal
- * @hidden
- */
- function isArray(val) {
- return Array.isArray(val) || mobx.isObservableArray(val);
- }
- /**
- * @internal
- * @hidden
- */
- function asArray(val) {
- if (!val)
- return EMPTY_ARRAY;
- if (isArray(val))
- return val;
- return [val];
- }
- /**
- * @internal
- * @hidden
- */
- function extend(a) {
- var b = [];
- for (var _i = 1; _i < arguments.length; _i++) {
- b[_i - 1] = arguments[_i];
- }
- for (var i = 0; i < b.length; i++) {
- var current = b[i];
- for (var key in current)
- a[key] = current[key];
- }
- return a;
- }
- /**
- * @internal
- * @hidden
- */
- function isPlainObject(value) {
- if (value === null || typeof value !== "object")
- return false;
- var proto = Object.getPrototypeOf(value);
- return proto === Object.prototype || proto === null;
- }
- /**
- * @internal
- * @hidden
- */
- function isMutable(value) {
- return (value !== null &&
- typeof value === "object" &&
- !(value instanceof Date) &&
- !(value instanceof RegExp));
- }
- /**
- * @internal
- * @hidden
- */
- function isPrimitive(value, includeDate) {
- if (includeDate === void 0) { includeDate = true; }
- if (value === null || value === undefined)
- return true;
- if (typeof value === "string" ||
- typeof value === "number" ||
- typeof value === "boolean" ||
- (includeDate && value instanceof Date))
- return true;
- return false;
- }
- /**
- * @internal
- * @hidden
- * Freeze a value and return it (if not in production)
- */
- function freeze(value) {
- if (!devMode())
- return value;
- return isPrimitive(value) || mobx.isObservableArray(value) ? value : Object.freeze(value);
- }
- /**
- * @internal
- * @hidden
- * Recursively freeze a value (if not in production)
- */
- function deepFreeze(value) {
- if (!devMode())
- return value;
- freeze(value);
- if (isPlainObject(value)) {
- Object.keys(value).forEach(function (propKey) {
- if (!isPrimitive(value[propKey]) &&
- !Object.isFrozen(value[propKey])) {
- deepFreeze(value[propKey]);
- }
- });
- }
- return value;
- }
- /**
- * @internal
- * @hidden
- */
- function isSerializable(value) {
- return typeof value !== "function";
- }
- /**
- * @internal
- * @hidden
- */
- function addHiddenFinalProp(object, propName, value) {
- Object.defineProperty(object, propName, {
- enumerable: false,
- writable: false,
- configurable: true,
- value: value
- });
- }
- /**
- * @internal
- * @hidden
- */
- function addHiddenWritableProp(object, propName, value) {
- Object.defineProperty(object, propName, {
- enumerable: false,
- writable: true,
- configurable: true,
- value: value
- });
- }
- /**
- * @internal
- * @hidden
- */
- var EventHandler = /** @class */ (function () {
- function EventHandler() {
- this.handlers = [];
- }
- Object.defineProperty(EventHandler.prototype, "hasSubscribers", {
- get: function () {
- return this.handlers.length > 0;
- },
- enumerable: true,
- configurable: true
- });
- EventHandler.prototype.register = function (fn, atTheBeginning) {
- var _this = this;
- if (atTheBeginning === void 0) { atTheBeginning = false; }
- if (atTheBeginning) {
- this.handlers.unshift(fn);
- }
- else {
- this.handlers.push(fn);
- }
- return function () {
- _this.unregister(fn);
- };
- };
- EventHandler.prototype.has = function (fn) {
- return this.handlers.indexOf(fn) >= 0;
- };
- EventHandler.prototype.unregister = function (fn) {
- var index = this.handlers.indexOf(fn);
- if (index >= 0) {
- this.handlers.splice(index, 1);
- }
- };
- EventHandler.prototype.clear = function () {
- this.handlers.length = 0;
- };
- EventHandler.prototype.emit = function () {
- var args = [];
- for (var _i = 0; _i < arguments.length; _i++) {
- args[_i] = arguments[_i];
- }
- // make a copy just in case it changes
- var handlers = this.handlers.slice();
- handlers.forEach(function (f) { return f.apply(void 0, __spread(args)); });
- };
- return EventHandler;
- }());
- /**
- * @internal
- * @hidden
- */
- var EventHandlers = /** @class */ (function () {
- function EventHandlers() {
- }
- EventHandlers.prototype.hasSubscribers = function (event) {
- var handler = this.eventHandlers && this.eventHandlers[event];
- return !!handler && handler.hasSubscribers;
- };
- EventHandlers.prototype.register = function (event, fn, atTheBeginning) {
- if (atTheBeginning === void 0) { atTheBeginning = false; }
- if (!this.eventHandlers) {
- this.eventHandlers = {};
- }
- var handler = this.eventHandlers[event];
- if (!handler) {
- handler = this.eventHandlers[event] = new EventHandler();
- }
- return handler.register(fn, atTheBeginning);
- };
- EventHandlers.prototype.has = function (event, fn) {
- var handler = this.eventHandlers && this.eventHandlers[event];
- return !!handler && handler.has(fn);
- };
- EventHandlers.prototype.unregister = function (event, fn) {
- var handler = this.eventHandlers && this.eventHandlers[event];
- if (handler) {
- handler.unregister(fn);
- }
- };
- EventHandlers.prototype.clear = function (event) {
- if (this.eventHandlers) {
- delete this.eventHandlers[event];
- }
- };
- EventHandlers.prototype.clearAll = function () {
- this.eventHandlers = undefined;
- };
- EventHandlers.prototype.emit = function (event) {
- var _a;
- var args = [];
- for (var _i = 1; _i < arguments.length; _i++) {
- args[_i - 1] = arguments[_i];
- }
- var handler = this.eventHandlers && this.eventHandlers[event];
- if (handler) {
- (_a = handler).emit.apply(_a, __spread(args));
- }
- };
- return EventHandlers;
- }());
- /**
- * @internal
- * @hidden
- */
- function argsToArray(args) {
- var res = new Array(args.length);
- for (var i = 0; i < args.length; i++)
- res[i] = args[i];
- return res;
- }
- /**
- * @internal
- * @hidden
- */
- function invalidateComputed(target, propName) {
- var atom = mobx.getAtom(target, propName);
- atom.trackAndCompute();
- }
- /**
- * @internal
- * @hidden
- */
- function stringStartsWith(str, beginning) {
- return str.indexOf(beginning) === 0;
- }
- /**
- * @internal
- * @hidden
- */
- var deprecated = function (id, message) {
- // skip if running production
- if (!devMode())
- return;
- // warn if hasn't been warned before
- if (deprecated.ids && !deprecated.ids.hasOwnProperty(id)) {
- warnError("Deprecation warning: " + message);
- }
- // mark as warned to avoid duplicate warn message
- if (deprecated.ids)
- deprecated.ids[id] = true;
- };
- deprecated.ids = {};
- /**
- * @internal
- * @hidden
- */
- function warnError(msg) {
- console.warn(new Error("[mobx-state-tree] " + msg));
- }
- /**
- * @internal
- * @hidden
- */
- function isTypeCheckingEnabled() {
- return (devMode() ||
- (typeof process !== "undefined" && process.env && process.env.ENABLE_TYPE_CHECK === "true"));
- }
- /**
- * @internal
- * @hidden
- */
- function devMode() {
- return process.env.NODE_ENV !== "production";
- }
- /**
- * @internal
- * @hidden
- */
- function assertArg(value, fn, typeName, argNumber) {
- if (devMode()) {
- if (!fn(value)) {
- // istanbul ignore next
- throw fail$1("expected " + typeName + " as argument " + asArray(argNumber).join(" or ") + ", got " + value + " instead");
- }
- }
- }
- /**
- * @internal
- * @hidden
- */
- function assertIsFunction(value, argNumber) {
- assertArg(value, function (fn) { return typeof fn === "function"; }, "function", argNumber);
- }
- /**
- * @internal
- * @hidden
- */
- function assertIsNumber(value, argNumber, min, max) {
- assertArg(value, function (n) { return typeof n === "number"; }, "number", argNumber);
- if (min !== undefined) {
- assertArg(value, function (n) { return n >= min; }, "number greater than " + min, argNumber);
- }
- if (max !== undefined) {
- assertArg(value, function (n) { return n <= max; }, "number lesser than " + max, argNumber);
- }
- }
- /**
- * @internal
- * @hidden
- */
- function assertIsString(value, argNumber, canBeEmpty) {
- if (canBeEmpty === void 0) { canBeEmpty = true; }
- assertArg(value, function (s) { return typeof s === "string"; }, "string", argNumber);
- if (!canBeEmpty) {
- assertArg(value, function (s) { return s !== ""; }, "not empty string", argNumber);
- }
- }
- /**
- * See [asynchronous actions](https://github.com/mobxjs/mobx-state-tree/blob/master/docs/async-actions.md).
- *
- * @returns The flow as a promise.
- */
- function flow(generator) {
- return createFlowSpawner(generator.name, generator);
- }
- /**
- * @deprecated Not needed since TS3.6.
- * Used for TypeScript to make flows that return a promise return the actual promise result.
- *
- * @param val
- * @returns
- */
- function castFlowReturn(val) {
- return val;
- }
- /**
- * @internal
- * @hidden
- */
- function createFlowSpawner(name, generator) {
- var spawner = function flowSpawner() {
- // Implementation based on https://github.com/tj/co/blob/master/index.js
- var runId = getNextActionId();
- var parentContext = getCurrentActionContext();
- if (!parentContext) {
- throw fail$1("a mst flow must always have a parent context");
- }
- var parentActionContext = getParentActionContext(parentContext);
- if (!parentActionContext) {
- throw fail$1("a mst flow must always have a parent action context");
- }
- var contextBase = {
- name: name,
- id: runId,
- tree: parentContext.tree,
- context: parentContext.context,
- parentId: parentContext.id,
- allParentIds: __spread(parentContext.allParentIds, [parentContext.id]),
- rootId: parentContext.rootId,
- parentEvent: parentContext,
- parentActionEvent: parentActionContext
- };
- var args = arguments;
- function wrap(fn, type, arg) {
- fn.$mst_middleware = spawner.$mst_middleware; // pick up any middleware attached to the flow
- runWithActionContext(__assign(__assign({}, contextBase), { type: type, args: [arg] }), fn);
- }
- return new Promise(function (resolve, reject) {
- var gen;
- var init = function asyncActionInit() {
- gen = generator.apply(null, arguments);
- onFulfilled(undefined); // kick off the flow
- };
- init.$mst_middleware = spawner.$mst_middleware;
- runWithActionContext(__assign(__assign({}, contextBase), { type: "flow_spawn", args: argsToArray(args) }), init);
- function onFulfilled(res) {
- var ret;
- try {
- // prettier-ignore
- wrap(function (r) { ret = gen.next(r); }, "flow_resume", res);
- }
- catch (e) {
- // prettier-ignore
- setImmediate(function () {
- wrap(function (r) { reject(e); }, "flow_throw", e);
- });
- return;
- }
- next(ret);
- return;
- }
- function onRejected(err) {
- var ret;
- try {
- // prettier-ignore
- wrap(function (r) { ret = gen.throw(r); }, "flow_resume_error", err); // or yieldError?
- }
- catch (e) {
- // prettier-ignore
- setImmediate(function () {
- wrap(function (r) { reject(e); }, "flow_throw", e);
- });
- return;
- }
- next(ret);
- }
- function next(ret) {
- if (ret.done) {
- // prettier-ignore
- setImmediate(function () {
- wrap(function (r) { resolve(r); }, "flow_return", ret.value);
- });
- return;
- }
- // TODO: support more type of values? See https://github.com/tj/co/blob/249bbdc72da24ae44076afd716349d2089b31c4c/index.js#L100
- if (!ret.value || typeof ret.value.then !== "function") {
- // istanbul ignore next
- throw fail$1("Only promises can be yielded to `async`, got: " + ret);
- }
- return ret.value.then(onFulfilled, onRejected);
- }
- });
- };
- return spawner;
- }
- /**
- * @internal
- * @hidden
- */
- function splitPatch(patch) {
- if (!("oldValue" in patch))
- throw fail$1("Patches without `oldValue` field cannot be inversed");
- return [stripPatch(patch), invertPatch(patch)];
- }
- /**
- * @internal
- * @hidden
- */
- function stripPatch(patch) {
- // strips `oldvalue` information from the patch, so that it becomes a patch conform the json-patch spec
- // this removes the ability to undo the patch
- switch (patch.op) {
- case "add":
- return { op: "add", path: patch.path, value: patch.value };
- case "remove":
- return { op: "remove", path: patch.path };
- case "replace":
- return { op: "replace", path: patch.path, value: patch.value };
- }
- }
- function invertPatch(patch) {
- switch (patch.op) {
- case "add":
- return {
- op: "remove",
- path: patch.path
- };
- case "remove":
- return {
- op: "add",
- path: patch.path,
- value: patch.oldValue
- };
- case "replace":
- return {
- op: "replace",
- path: patch.path,
- value: patch.oldValue
- };
- }
- }
- /**
- * Simple simple check to check it is a number.
- */
- function isNumber(x) {
- return typeof x === "number";
- }
- /**
- * Escape slashes and backslashes.
- *
- * http://tools.ietf.org/html/rfc6901
- */
- function escapeJsonPath(path) {
- if (isNumber(path) === true) {
- return "" + path;
- }
- if (path.indexOf("/") === -1 && path.indexOf("~") === -1)
- return path;
- return path.replace(/~/g, "~0").replace(/\//g, "~1");
- }
- /**
- * Unescape slashes and backslashes.
- */
- function unescapeJsonPath(path) {
- return path.replace(/~1/g, "/").replace(/~0/g, "~");
- }
- /**
- * Generates a json-path compliant json path from path parts.
- *
- * @param path
- * @returns
- */
- function joinJsonPath(path) {
- // `/` refers to property with an empty name, while `` refers to root itself!
- if (path.length === 0)
- return "";
- var getPathStr = function (p) { return p.map(escapeJsonPath).join("/"); };
- if (path[0] === "." || path[0] === "..") {
- // relative
- return getPathStr(path);
- }
- else {
- // absolute
- return "/" + getPathStr(path);
- }
- }
- /**
- * Splits and decodes a json path into several parts.
- *
- * @param path
- * @returns
- */
- function splitJsonPath(path) {
- // `/` refers to property with an empty name, while `` refers to root itself!
- var parts = path.split("/").map(unescapeJsonPath);
- var valid = path === "" ||
- path === "." ||
- path === ".." ||
- stringStartsWith(path, "/") ||
- stringStartsWith(path, "./") ||
- stringStartsWith(path, "../");
- if (!valid) {
- throw fail$1("a json path must be either rooted, empty or relative, but got '" + path + "'");
- }
- // '/a/b/c' -> ["a", "b", "c"]
- // '../../b/c' -> ["..", "..", "b", "c"]
- // '' -> []
- // '/' -> ['']
- // './a' -> [".", "a"]
- // /./a' -> [".", "a"] equivalent to './a'
- if (parts[0] === "") {
- parts.shift();
- }
- return parts;
- }
- var SnapshotProcessor = /** @class */ (function (_super) {
- __extends(SnapshotProcessor, _super);
- function SnapshotProcessor(_subtype, _processors, name) {
- var _this = _super.call(this, name || _subtype.name) || this;
- _this._subtype = _subtype;
- _this._processors = _processors;
- return _this;
- }
- Object.defineProperty(SnapshotProcessor.prototype, "flags", {
- get: function () {
- return this._subtype.flags | TypeFlags.SnapshotProcessor;
- },
- enumerable: true,
- configurable: true
- });
- SnapshotProcessor.prototype.describe = function () {
- return "snapshotProcessor(" + this._subtype.describe() + ")";
- };
- SnapshotProcessor.prototype.preProcessSnapshot = function (sn) {
- if (this._processors.preProcessor) {
- return this._processors.preProcessor.call(null, sn);
- }
- return sn;
- };
- SnapshotProcessor.prototype.postProcessSnapshot = function (sn) {
- if (this._processors.postProcessor) {
- return this._processors.postProcessor.call(null, sn);
- }
- return sn;
- };
- SnapshotProcessor.prototype._fixNode = function (node) {
- var _this = this;
- // the node has to use these methods rather than the original type ones
- proxyNodeTypeMethods(node.type, this, "isAssignableFrom", "create");
- var oldGetSnapshot = node.getSnapshot;
- node.getSnapshot = function () {
- return _this.postProcessSnapshot(oldGetSnapshot.call(node));
- };
- };
- SnapshotProcessor.prototype.instantiate = function (parent, subpath, environment, initialValue) {
- var processedInitialValue = isStateTreeNode(initialValue)
- ? initialValue
- : this.preProcessSnapshot(initialValue);
- var node = this._subtype.instantiate(parent, subpath, environment, processedInitialValue);
- this._fixNode(node);
- return node;
- };
- SnapshotProcessor.prototype.reconcile = function (current, newValue, parent, subpath) {
- var node = this._subtype.reconcile(current, isStateTreeNode(newValue) ? newValue : this.preProcessSnapshot(newValue), parent, subpath);
- if (node !== current) {
- this._fixNode(node);
- }
- return node;
- };
- SnapshotProcessor.prototype.getSnapshot = function (node, applyPostProcess) {
- if (applyPostProcess === void 0) { applyPostProcess = true; }
- var sn = this._subtype.getSnapshot(node);
- return applyPostProcess ? this.postProcessSnapshot(sn) : sn;
- };
- SnapshotProcessor.prototype.isValidSnapshot = function (value, context) {
- var processedSn = this.preProcessSnapshot(value);
- return this._subtype.validate(processedSn, context);
- };
- SnapshotProcessor.prototype.getSubTypes = function () {
- return this._subtype;
- };
- SnapshotProcessor.prototype.is = function (thing) {
- return (this._subtype.validate(isType(thing) ? this._subtype : this.preProcessSnapshot(thing), [
- { path: "", type: this._subtype }
- ]).length === 0);
- };
- return SnapshotProcessor;
- }(BaseType));
- function proxyNodeTypeMethods(nodeType, snapshotProcessorType) {
- var e_1, _a;
- var methods = [];
- for (var _i = 2; _i < arguments.length; _i++) {
- methods[_i - 2] = arguments[_i];
- }
- try {
- for (var methods_1 = __values(methods), methods_1_1 = methods_1.next(); !methods_1_1.done; methods_1_1 = methods_1.next()) {
- var method = methods_1_1.value;
- nodeType[method] = snapshotProcessorType[method].bind(snapshotProcessorType);
- }
- }
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
- finally {
- try {
- if (methods_1_1 && !methods_1_1.done && (_a = methods_1.return)) _a.call(methods_1);
- }
- finally { if (e_1) throw e_1.error; }
- }
- }
- /**
- * `types.snapshotProcessor` - Runs a pre/post snapshot processor before/after serializing a given type.
- *
- * Example:
- * ```ts
- * const Todo1 = types.model({ text: types.string })
- * // in the backend the text type must be null when empty
- * interface BackendTodo {
- * text: string | null
- * }
- * const Todo2 = types.snapshotProcessor(Todo1, {
- * // from snapshot to instance
- * preProcessor(sn: BackendTodo) {
- * return {
- * text: sn.text || "";
- * }
- * },
- * // from instance to snapshot
- * postProcessor(sn): BackendTodo {
- * return {
- * text: !sn.text ? null : sn.text
- * }
- * }
- * })
- * ```
- *
- * @param type Type to run the processors over.
- * @param processors Processors to run.
- * @param name Type name, or undefined to inherit the inner type one.
- * @returns
- */
- function snapshotProcessor(type, processors, name) {
- assertIsType(type, 1);
- if (devMode()) {
- if (processors.postProcessor && typeof processors.postProcessor !== "function") {
- // istanbul ignore next
- throw fail("postSnapshotProcessor must be a function");
- }
- if (processors.preProcessor && typeof processors.preProcessor !== "function") {
- // istanbul ignore next
- throw fail("preSnapshotProcessor must be a function");
- }
- }
- return new SnapshotProcessor(type, processors, name);
- }
- var needsIdentifierError = "Map.put can only be used to store complex values that have an identifier type attribute";
- function tryCollectModelTypes(type, modelTypes) {
- var e_1, _a;
- var subtypes = type.getSubTypes();
- if (subtypes === cannotDetermineSubtype) {
- return false;
- }
- if (subtypes) {
- var subtypesArray = asArray(subtypes);
- try {
- for (var subtypesArray_1 = __values(subtypesArray), subtypesArray_1_1 = subtypesArray_1.next(); !subtypesArray_1_1.done; subtypesArray_1_1 = subtypesArray_1.next()) {
- var subtype = subtypesArray_1_1.value;
- if (!tryCollectModelTypes(subtype, modelTypes))
- return false;
- }
- }
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
- finally {
- try {
- if (subtypesArray_1_1 && !subtypesArray_1_1.done && (_a = subtypesArray_1.return)) _a.call(subtypesArray_1);
- }
- finally { if (e_1) throw e_1.error; }
- }
- }
- if (type instanceof ModelType) {
- modelTypes.push(type);
- }
- return true;
- }
- /**
- * @internal
- * @hidden
- */
- var MapIdentifierMode;
- (function (MapIdentifierMode) {
- MapIdentifierMode[MapIdentifierMode["UNKNOWN"] = 0] = "UNKNOWN";
- MapIdentifierMode[MapIdentifierMode["YES"] = 1] = "YES";
- MapIdentifierMode[MapIdentifierMode["NO"] = 2] = "NO";
- })(MapIdentifierMode || (MapIdentifierMode = {}));
- var MSTMap = /** @class */ (function (_super) {
- __extends(MSTMap, _super);
- function MSTMap(initialData) {
- return _super.call(this, initialData, mobx.observable.ref.enhancer) || this;
- }
- MSTMap.prototype.get = function (key) {
- // maybe this is over-enthousiastic? normalize numeric keys to strings
- return _super.prototype.get.call(this, "" + key);
- };
- MSTMap.prototype.has = function (key) {
- return _super.prototype.has.call(this, "" + key);
- };
- MSTMap.prototype.delete = function (key) {
- return _super.prototype.delete.call(this, "" + key);
- };
- MSTMap.prototype.set = function (key, value) {
- return _super.prototype.set.call(this, "" + key, value);
- };
- MSTMap.prototype.put = function (value) {
- if (!value)
- throw fail$1("Map.put cannot be used to set empty values");
- if (isStateTreeNode(value)) {
- var node = getStateTreeNode(value);
- if (devMode()) {
- if (!node.identifierAttribute) {
- throw fail$1(needsIdentifierError);
- }
- }
- if (node.identifier === null) {
- throw fail$1(needsIdentifierError);
- }
- this.set(node.identifier, value);
- return value;
- }
- else if (!isMutable(value)) {
- throw fail$1("Map.put can only be used to store complex values");
- }
- else {
- var mapNode = getStateTreeNode(this);
- var mapType = mapNode.type;
- if (mapType.identifierMode !== MapIdentifierMode.YES) {
- throw fail$1(needsIdentifierError);
- }
- var idAttr = mapType.mapIdentifierAttribute;
- var id = value[idAttr];
- if (!isValidIdentifier(id)) {
- // try again but this time after creating a node for the value
- // since it might be an optional identifier
- var newNode = this.put(mapType.getChildType().create(value, mapNode.environment));
- return this.put(getSnapshot(newNode));
- }
- var key = normalizeIdentifier(id);
- this.set(key, value);
- return this.get(key);
- }
- };
- return MSTMap;
- }(mobx.ObservableMap));
- /**
- * @internal
- * @hidden
- */
- var MapType = /** @class */ (function (_super) {
- __extends(MapType, _super);
- function MapType(name, _subType, hookInitializers) {
- if (hookInitializers === void 0) { hookInitializers = []; }
- var _this = _super.call(this, name) || this;
- _this._subType = _subType;
- _this.identifierMode = MapIdentifierMode.UNKNOWN;
- _this.mapIdentifierAttribute = undefined;
- _this.flags = TypeFlags.Map;
- _this.hookInitializers = [];
- _this._determineIdentifierMode();
- _this.hookInitializers = hookInitializers;
- return _this;
- }
- MapType.prototype.hooks = function (hooks) {
- var hookInitializers = this.hookInitializers.length > 0 ? this.hookInitializers.concat(hooks) : [hooks];
- return new MapType(this.name, this._subType, hookInitializers);
- };
- MapType.prototype.instantiate = function (parent, subpath, environment, initialValue) {
- this._determineIdentifierMode();
- return createObjectNode(this, parent, subpath, environment, initialValue);
- };
- MapType.prototype._determineIdentifierMode = function () {
- if (this.identifierMode !== MapIdentifierMode.UNKNOWN) {
- return;
- }
- var modelTypes = [];
- if (tryCollectModelTypes(this._subType, modelTypes)) {
- var identifierAttribute_1 = undefined;
- modelTypes.forEach(function (type) {
- if (type.identifierAttribute) {
- if (identifierAttribute_1 && identifierAttribute_1 !== type.identifierAttribute) {
- throw fail$1("The objects in a map should all have the same identifier attribute, expected '" + identifierAttribute_1 + "', but child of type '" + type.name + "' declared attribute '" + type.identifierAttribute + "' as identifier");
- }
- identifierAttribute_1 = type.identifierAttribute;
- }
- });
- if (identifierAttribute_1) {
- this.identifierMode = MapIdentifierMode.YES;
- this.mapIdentifierAttribute = identifierAttribute_1;
- }
- else {
- this.identifierMode = MapIdentifierMode.NO;
- }
- }
- };
- MapType.prototype.initializeChildNodes = function (objNode, initialSnapshot) {
- if (initialSnapshot === void 0) { initialSnapshot = {}; }
- var subType = objNode.type._subType;
- var result = {};
- Object.keys(initialSnapshot).forEach(function (name) {
- result[name] = subType.instantiate(objNode, name, undefined, initialSnapshot[name]);
- });
- return result;
- };
- MapType.prototype.createNewInstance = function (childNodes) {
- return new MSTMap(childNodes);
- };
- MapType.prototype.finalizeNewInstance = function (node, instance) {
- mobx._interceptReads(instance, node.unbox);
- var type = node.type;
- type.hookInitializers.forEach(function (initializer) {
- var hooks = initializer(instance);
- Object.keys(hooks).forEach(function (name) {
- var hook = hooks[name];
- var actionInvoker = createActionInvoker(instance, name, hook);
- (!devMode() ? addHiddenFinalProp : addHiddenWritableProp)(instance, name, actionInvoker);
- });
- });
- mobx.intercept(instance, this.willChange);
- mobx.observe(instance, this.didChange);
- };
- MapType.prototype.describe = function () {
- return "Map<string, " + this._subType.describe() + ">";
- };
- MapType.prototype.getChildren = function (node) {
- // return (node.storedValue as ObservableMap<any>).values()
- return mobx.values(node.storedValue);
- };
- MapType.prototype.getChildNode = function (node, key) {
- var childNode = node.storedValue.get("" + key);
- if (!childNode)
- throw fail$1("Not a child " + key);
- return childNode;
- };
- MapType.prototype.willChange = function (change) {
- var node = getStateTreeNode(change.object);
- var key = change.name;
- node.assertWritable({ subpath: key });
- var mapType = node.type;
- var subType = mapType._subType;
- switch (change.type) {
- case "update":
- {
- var newValue = change.newValue;
- var oldValue = change.object.get(key);
- if (newValue === oldValue)
- return null;
- typecheckInternal(subType, newValue);
- change.newValue = subType.reconcile(node.getChildNode(key), change.newValue, node, key);
- mapType.processIdentifier(key, change.newValue);
- }
- break;
- case "add":
- {
- typecheckInternal(subType, change.newValue);
- change.newValue = subType.instantiate(node, key, undefined, change.newValue);
- mapType.processIdentifier(key, change.newValue);
- }
- break;
- }
- return change;
- };
- MapType.prototype.processIdentifier = function (expected, node) {
- if (this.identifierMode === MapIdentifierMode.YES && node instanceof ObjectNode) {
- var identifier = node.identifier;
- if (identifier !== expected)
- throw fail$1("A map of objects containing an identifier should always store the object under their own identifier. Trying to store key '" + identifier + "', but expected: '" + expected + "'");
- }
- };
- MapType.prototype.getSnapshot = function (node) {
- var res = {};
- node.getChildren().forEach(function (childNode) {
- res[childNode.subpath] = childNode.snapshot;
- });
- return res;
- };
- MapType.prototype.processInitialSnapshot = function (childNodes) {
- var processed = {};
- Object.keys(childNodes).forEach(function (key) {
- processed[key] = childNodes[key].getSnapshot();
- });
- return processed;
- };
- MapType.prototype.didChange = function (change) {
- var node = getStateTreeNode(change.object);
- switch (change.type) {
- case "update":
- return void node.emitPatch({
- op: "replace",
- path: escapeJsonPath(change.name),
- value: change.newValue.snapshot,
- oldValue: change.oldValue ? change.oldValue.snapshot : undefined
- }, node);
- case "add":
- return void node.emitPatch({
- op: "add",
- path: escapeJsonPath(change.name),
- value: change.newValue.snapshot,
- oldValue: undefined
- }, node);
- case "delete":
- // a node got deleted, get the old snapshot and make the node die
- var oldSnapshot = change.oldValue.snapshot;
- change.oldValue.die();
- // emit the patch
- return void node.emitPatch({
- op: "remove",
- path: escapeJsonPath(change.name),
- oldValue: oldSnapshot
- }, node);
- }
- };
- MapType.prototype.applyPatchLocally = function (node, subpath, patch) {
- var target = node.storedValue;
- switch (patch.op) {
- case "add":
- case "replace":
- target.set(subpath, patch.value);
- break;
- case "remove":
- target.delete(subpath);
- break;
- }
- };
- MapType.prototype.applySnapshot = function (node, snapshot) {
- typecheckInternal(this, snapshot);
- var target = node.storedValue;
- var currentKeys = {};
- Array.from(target.keys()).forEach(function (key) {
- currentKeys[key] = false;
- });
- if (snapshot) {
- // Don't use target.replace, as it will throw away all existing items first
- for (var key in snapshot) {
- target.set(key, snapshot[key]);
- currentKeys["" + key] = true;
- }
- }
- Object.keys(currentKeys).forEach(function (key) {
- if (currentKeys[key] === false)
- target.delete(key);
- });
- };
- MapType.prototype.getChildType = function () {
- return this._subType;
- };
- MapType.prototype.isValidSnapshot = function (value, context) {
- var _this = this;
- if (!isPlainObject(value)) {
- return typeCheckFailure(context, value, "Value is not a plain object");
- }
- return flattenTypeErrors(Object.keys(value).map(function (path) {
- return _this._subType.validate(value[path], getContextForPath(context, path, _this._subType));
- }));
- };
- MapType.prototype.getDefaultSnapshot = function () {
- return EMPTY_OBJECT;
- };
- MapType.prototype.removeChild = function (node, subpath) {
- node.storedValue.delete(subpath);
- };
- __decorate([
- mobx.action
- ], MapType.prototype, "applySnapshot", null);
- return MapType;
- }(ComplexType));
- /**
- * `types.map` - Creates a key based collection type who's children are all of a uniform declared type.
- * If the type stored in a map has an identifier, it is mandatory to store the child under that identifier in the map.
- *
- * This type will always produce [observable maps](https://mobx.js.org/refguide/map.html)
- *
- * Example:
- * ```ts
- * const Todo = types.model({
- * id: types.identifier,
- * task: types.string
- * })
- *
- * const TodoStore = types.model({
- * todos: types.map(Todo)
- * })
- *
- * const s = TodoStore.create({ todos: {} })
- * unprotect(s)
- * s.todos.set(17, { task: "Grab coffee", id: 17 })
- * s.todos.put({ task: "Grab cookie", id: 18 }) // put will infer key from the identifier
- * console.log(s.todos.get(17).task) // prints: "Grab coffee"
- * ```
- *
- * @param subtype
- * @returns
- */
- function map(subtype) {
- return new MapType("map<string, " + subtype.name + ">", subtype);
- }
- /**
- * Returns if a given value represents a map type.
- *
- * @param type
- * @returns `true` if it is a map type.
- */
- function isMapType(type) {
- return isType(type) && (type.flags & TypeFlags.Map) > 0;
- }
- /**
- * @internal
- * @hidden
- */
- var ArrayType = /** @class */ (function (_super) {
- __extends(ArrayType, _super);
- function ArrayType(name, _subType, hookInitializers) {
- if (hookInitializers === void 0) { hookInitializers = []; }
- var _this = _super.call(this, name) || this;
- _this._subType = _subType;
- _this.flags = TypeFlags.Array;
- _this.hookInitializers = [];
- _this.hookInitializers = hookInitializers;
- return _this;
- }
- ArrayType.prototype.hooks = function (hooks) {
- var hookInitializers = this.hookInitializers.length > 0 ? this.hookInitializers.concat(hooks) : [hooks];
- return new ArrayType(this.name, this._subType, hookInitializers);
- };
- ArrayType.prototype.instantiate = function (parent, subpath, environment, initialValue) {
- return createObjectNode(this, parent, subpath, environment, initialValue);
- };
- ArrayType.prototype.initializeChildNodes = function (objNode, snapshot) {
- if (snapshot === void 0) { snapshot = []; }
- var subType = objNode.type._subType;
- var result = {};
- snapshot.forEach(function (item, index) {
- var subpath = "" + index;
- result[subpath] = subType.instantiate(objNode, subpath, undefined, item);
- });
- return result;
- };
- ArrayType.prototype.createNewInstance = function (childNodes) {
- return mobx.observable.array(convertChildNodesToArray(childNodes), mobxShallow);
- };
- ArrayType.prototype.finalizeNewInstance = function (node, instance) {
- mobx._getAdministration(instance).dehancer = node.unbox;
- var type = node.type;
- type.hookInitializers.forEach(function (initializer) {
- var hooks = initializer(instance);
- Object.keys(hooks).forEach(function (name) {
- var hook = hooks[name];
- var actionInvoker = createActionInvoker(instance, name, hook);
- (!devMode() ? addHiddenFinalProp : addHiddenWritableProp)(instance, name, actionInvoker);
- });
- });
- mobx.intercept(instance, this.willChange);
- mobx.observe(instance, this.didChange);
- };
- ArrayType.prototype.describe = function () {
- return this._subType.describe() + "[]";
- };
- ArrayType.prototype.getChildren = function (node) {
- return node.storedValue.slice();
- };
- ArrayType.prototype.getChildNode = function (node, key) {
- var index = Number(key);
- if (index < node.storedValue.length)
- return node.storedValue[index];
- throw fail$1("Not a child: " + key);
- };
- ArrayType.prototype.willChange = function (change) {
- var node = getStateTreeNode(change.object);
- node.assertWritable({ subpath: "" + change.index });
- var subType = node.type._subType;
- var childNodes = node.getChildren();
- switch (change.type) {
- case "update":
- {
- if (change.newValue === change.object[change.index])
- return null;
- var updatedNodes = reconcileArrayChildren(node, subType, [childNodes[change.index]], [change.newValue], [change.index]);
- if (!updatedNodes) {
- return null;
- }
- change.newValue = updatedNodes[0];
- }
- break;
- case "splice":
- {
- var index_1 = change.index, removedCount = change.removedCount, added = change.added;
- var addedNodes = reconcileArrayChildren(node, subType, childNodes.slice(index_1, index_1 + removedCount), added, added.map(function (_, i) { return index_1 + i; }));
- if (!addedNodes) {
- return null;
- }
- change.added = addedNodes;
- // update paths of remaining items
- for (var i = index_1 + removedCount; i < childNodes.length; i++) {
- childNodes[i].setParent(node, "" + (i + added.length - removedCount));
- }
- }
- break;
- }
- return change;
- };
- ArrayType.prototype.getSnapshot = function (node) {
- return node.getChildren().map(function (childNode) { return childNode.snapshot; });
- };
- ArrayType.prototype.processInitialSnapshot = function (childNodes) {
- var processed = [];
- Object.keys(childNodes).forEach(function (key) {
- processed.push(childNodes[key].getSnapshot());
- });
- return processed;
- };
- ArrayType.prototype.didChange = function (change) {
- var node = getStateTreeNode(change.object);
- switch (change.type) {
- case "update":
- return void node.emitPatch({
- op: "replace",
- path: "" + change.index,
- value: change.newValue.snapshot,
- oldValue: change.oldValue ? change.oldValue.snapshot : undefined
- }, node);
- case "splice":
- for (var i = change.removedCount - 1; i >= 0; i--)
- node.emitPatch({
- op: "remove",
- path: "" + (change.index + i),
- oldValue: change.removed[i].snapshot
- }, node);
- for (var i = 0; i < change.addedCount; i++)
- node.emitPatch({
- op: "add",
- path: "" + (change.index + i),
- value: node.getChildNode("" + (change.index + i)).snapshot,
- oldValue: undefined
- }, node);
- return;
- }
- };
- ArrayType.prototype.applyPatchLocally = function (node, subpath, patch) {
- var target = node.storedValue;
- var index = subpath === "-" ? target.length : Number(subpath);
- switch (patch.op) {
- case "replace":
- target[index] = patch.value;
- break;
- case "add":
- target.splice(index, 0, patch.value);
- break;
- case "remove":
- target.splice(index, 1);
- break;
- }
- };
- ArrayType.prototype.applySnapshot = function (node, snapshot) {
- typecheckInternal(this, snapshot);
- var target = node.storedValue;
- target.replace(snapshot);
- };
- ArrayType.prototype.getChildType = function () {
- return this._subType;
- };
- ArrayType.prototype.isValidSnapshot = function (value, context) {
- var _this = this;
- if (!isArray(value)) {
- return typeCheckFailure(context, value, "Value is not an array");
- }
- return flattenTypeErrors(value.map(function (item, index) {
- return _this._subType.validate(item, getContextForPath(context, "" + index, _this._subType));
- }));
- };
- ArrayType.prototype.getDefaultSnapshot = function () {
- return EMPTY_ARRAY;
- };
- ArrayType.prototype.removeChild = function (node, subpath) {
- node.storedValue.splice(Number(subpath), 1);
- };
- __decorate([
- mobx.action
- ], ArrayType.prototype, "applySnapshot", null);
- return ArrayType;
- }(ComplexType));
- /**
- * `types.array` - Creates an index based collection type who's children are all of a uniform declared type.
- *
- * This type will always produce [observable arrays](https://mobx.js.org/refguide/array.html)
- *
- * Example:
- * ```ts
- * const Todo = types.model({
- * task: types.string
- * })
- *
- * const TodoStore = types.model({
- * todos: types.array(Todo)
- * })
- *
- * const s = TodoStore.create({ todos: [] })
- * unprotect(s) // needed to allow modifying outside of an action
- * s.todos.push({ task: "Grab coffee" })
- * console.log(s.todos[0]) // prints: "Grab coffee"
- * ```
- *
- * @param subtype
- * @returns
- */
- function array(subtype) {
- assertIsType(subtype, 1);
- return new ArrayType(subtype.name + "[]", subtype);
- }
- function reconcileArrayChildren(parent, childType, oldNodes, newValues, newPaths) {
- var nothingChanged = true;
- for (var i = 0;; i++) {
- var hasNewNode = i <= newValues.length - 1;
- var oldNode = oldNodes[i];
- var newValue = hasNewNode ? newValues[i] : undefined;
- var newPath = "" + newPaths[i];
- // for some reason, instead of newValue we got a node, fallback to the storedValue
- // TODO: https://github.com/mobxjs/mobx-state-tree/issues/340#issuecomment-325581681
- if (isNode(newValue))
- newValue = newValue.storedValue;
- if (!oldNode && !hasNewNode) {
- // both are empty, end
- break;
- }
- else if (!hasNewNode) {
- // new one does not exists
- nothingChanged = false;
- oldNodes.splice(i, 1);
- if (oldNode instanceof ObjectNode) {
- // since it is going to be returned by pop/splice/shift better create it before killing it
- // so it doesn't end up in an undead state
- oldNode.createObservableInstanceIfNeeded();
- }
- oldNode.die();
- i--;
- }
- else if (!oldNode) {
- // there is no old node, create it
- // check if already belongs to the same parent. if so, avoid pushing item in. only swapping can occur.
- if (isStateTreeNode(newValue) && getStateTreeNode(newValue).parent === parent) {
- // this node is owned by this parent, but not in the reconcilable set, so it must be double
- throw fail$1("Cannot add an object to a state tree if it is already part of the same or another state tree. Tried to assign an object to '" + parent.path + "/" + newPath + "', but it lives already at '" + getStateTreeNode(newValue).path + "'");
- }
- nothingChanged = false;
- var newNode = valueAsNode(childType, parent, newPath, newValue);
- oldNodes.splice(i, 0, newNode);
- }
- else if (areSame(oldNode, newValue)) {
- // both are the same, reconcile
- oldNodes[i] = valueAsNode(childType, parent, newPath, newValue, oldNode);
- }
- else {
- // nothing to do, try to reorder
- var oldMatch = undefined;
- // find a possible candidate to reuse
- for (var j = i; j < oldNodes.length; j++) {
- if (areSame(oldNodes[j], newValue)) {
- oldMatch = oldNodes.splice(j, 1)[0];
- break;
- }
- }
- nothingChanged = false;
- var newNode = valueAsNode(childType, parent, newPath, newValue, oldMatch);
- oldNodes.splice(i, 0, newNode);
- }
- }
- return nothingChanged ? null : oldNodes;
- }
- /**
- * Convert a value to a node at given parent and subpath. Attempts to reuse old node if possible and given.
- */
- function valueAsNode(childType, parent, subpath, newValue, oldNode) {
- // ensure the value is valid-ish
- typecheckInternal(childType, newValue);
- function getNewNode() {
- // the new value has a MST node
- if (isStateTreeNode(newValue)) {
- var childNode = getStateTreeNode(newValue);
- childNode.assertAlive(EMPTY_OBJECT);
- // the node lives here
- if (childNode.parent !== null && childNode.parent === parent) {
- childNode.setParent(parent, subpath);
- return childNode;
- }
- }
- // there is old node and new one is a value/snapshot
- if (oldNode) {
- return childType.reconcile(oldNode, newValue, parent, subpath);
- }
- // nothing to do, create from scratch
- return childType.instantiate(parent, subpath, undefined, newValue);
- }
- var newNode = getNewNode();
- if (oldNode && oldNode !== newNode) {
- if (oldNode instanceof ObjectNode) {
- // since it is going to be returned by pop/splice/shift better create it before killing it
- // so it doesn't end up in an undead state
- oldNode.createObservableInstanceIfNeeded();
- }
- oldNode.die();
- }
- return newNode;
- }
- /**
- * Check if a node holds a value.
- */
- function areSame(oldNode, newValue) {
- // never consider dead old nodes for reconciliation
- if (!oldNode.isAlive) {
- return false;
- }
- // the new value has the same node
- if (isStateTreeNode(newValue)) {
- var newNode = getStateTreeNode(newValue);
- return newNode.isAlive && newNode === oldNode;
- }
- // the provided value is the snapshot of the old node
- if (oldNode.snapshot === newValue) {
- return true;
- }
- // new value is a snapshot with the correct identifier
- return (oldNode instanceof ObjectNode &&
- oldNode.identifier !== null &&
- oldNode.identifierAttribute &&
- isPlainObject(newValue) &&
- oldNode.identifier === normalizeIdentifier(newValue[oldNode.identifierAttribute]) &&
- oldNode.type.is(newValue));
- }
- /**
- * Returns if a given value represents an array type.
- *
- * @param type
- * @returns `true` if the type is an array type.
- */
- function isArrayType(type) {
- return isType(type) && (type.flags & TypeFlags.Array) > 0;
- }
- var PRE_PROCESS_SNAPSHOT = "preProcessSnapshot";
- var POST_PROCESS_SNAPSHOT = "postProcessSnapshot";
- function objectTypeToString() {
- return getStateTreeNode(this).toString();
- }
- var defaultObjectOptions = {
- name: "AnonymousModel",
- properties: {},
- initializers: EMPTY_ARRAY
- };
- function toPropertiesObject(declaredProps) {
- // loop through properties and ensures that all items are types
- return Object.keys(declaredProps).reduce(function (props, key) {
- var _a, _b, _c;
- // warn if user intended a HOOK
- if (key in Hook)
- throw fail$1("Hook '" + key + "' was defined as property. Hooks should be defined as part of the actions");
- // the user intended to use a view
- var descriptor = Object.getOwnPropertyDescriptor(props, key);
- if ("get" in descriptor) {
- throw fail$1("Getters are not supported as properties. Please use views instead");
- }
- // undefined and null are not valid
- var value = descriptor.value;
- if (value === null || value === undefined) {
- throw fail$1("The default value of an attribute cannot be null or undefined as the type cannot be inferred. Did you mean `types.maybe(someType)`?");
- // its a primitive, convert to its type
- }
- else if (isPrimitive(value)) {
- return Object.assign({}, props, (_a = {},
- _a[key] = optional(getPrimitiveFactoryFromValue(value), value),
- _a));
- // map defaults to empty object automatically for models
- }
- else if (value instanceof MapType) {
- return Object.assign({}, props, (_b = {},
- _b[key] = optional(value, {}),
- _b));
- }
- else if (value instanceof ArrayType) {
- return Object.assign({}, props, (_c = {}, _c[key] = optional(value, []), _c));
- // its already a type
- }
- else if (isType(value)) {
- return props;
- // its a function, maybe the user wanted a view?
- }
- else if (devMode() && typeof value === "function") {
- throw fail$1("Invalid type definition for property '" + key + "', it looks like you passed a function. Did you forget to invoke it, or did you intend to declare a view / action?");
- // no other complex values
- }
- else if (devMode() && typeof value === "object") {
- throw fail$1("Invalid type definition for property '" + key + "', it looks like you passed an object. Try passing another model type or a types.frozen.");
- // WTF did you pass in mate?
- }
- else {
- throw fail$1("Invalid type definition for property '" + key + "', cannot infer a type from a value like '" + value + "' (" + typeof value + ")");
- }
- }, declaredProps);
- }
- /**
- * @internal
- * @hidden
- */
- var ModelType = /** @class */ (function (_super) {
- __extends(ModelType, _super);
- function ModelType(opts) {
- var _this = _super.call(this, opts.name || defaultObjectOptions.name) || this;
- _this.flags = TypeFlags.Object;
- _this.named = function (name) {
- return _this.cloneAndEnhance({ name: name });
- };
- _this.props = function (properties) {
- return _this.cloneAndEnhance({ properties: properties });
- };
- _this.preProcessSnapshot = function (preProcessor) {
- var currentPreprocessor = _this.preProcessor;
- if (!currentPreprocessor)
- return _this.cloneAndEnhance({ preProcessor: preProcessor });
- else
- return _this.cloneAndEnhance({
- preProcessor: function (snapshot) { return currentPreprocessor(preProcessor(snapshot)); }
- });
- };
- _this.postProcessSnapshot = function (postProcessor) {
- var currentPostprocessor = _this.postProcessor;
- if (!currentPostprocessor)
- return _this.cloneAndEnhance({ postProcessor: postProcessor });
- else
- return _this.cloneAndEnhance({
- postProcessor: function (snapshot) { return postProcessor(currentPostprocessor(snapshot)); }
- });
- };
- Object.assign(_this, defaultObjectOptions, opts);
- // ensures that any default value gets converted to its related type
- _this.properties = toPropertiesObject(_this.properties);
- freeze(_this.properties); // make sure nobody messes with it
- _this.propertyNames = Object.keys(_this.properties);
- _this.identifierAttribute = _this._getIdentifierAttribute();
- return _this;
- }
- ModelType.prototype._getIdentifierAttribute = function () {
- var identifierAttribute = undefined;
- this.forAllProps(function (propName, propType) {
- if (propType.flags & TypeFlags.Identifier) {
- if (identifierAttribute)
- throw fail$1("Cannot define property '" + propName + "' as object identifier, property '" + identifierAttribute + "' is already defined as identifier property");
- identifierAttribute = propName;
- }
- });
- return identifierAttribute;
- };
- ModelType.prototype.cloneAndEnhance = function (opts) {
- return new ModelType({
- name: opts.name || this.name,
- properties: Object.assign({}, this.properties, opts.properties),
- initializers: this.initializers.concat(opts.initializers || []),
- preProcessor: opts.preProcessor || this.preProcessor,
- postProcessor: opts.postProcessor || this.postProcessor
- });
- };
- ModelType.prototype.actions = function (fn) {
- var _this = this;
- var actionInitializer = function (self) {
- _this.instantiateActions(self, fn(self));
- return self;
- };
- return this.cloneAndEnhance({ initializers: [actionInitializer] });
- };
- ModelType.prototype.instantiateActions = function (self, actions) {
- // check if return is correct
- if (!isPlainObject(actions))
- throw fail$1("actions initializer should return a plain object containing actions");
- // bind actions to the object created
- Object.keys(actions).forEach(function (name) {
- // warn if preprocessor was given
- if (name === PRE_PROCESS_SNAPSHOT)
- throw fail$1("Cannot define action '" + PRE_PROCESS_SNAPSHOT + "', it should be defined using 'type.preProcessSnapshot(fn)' instead");
- // warn if postprocessor was given
- if (name === POST_PROCESS_SNAPSHOT)
- throw fail$1("Cannot define action '" + POST_PROCESS_SNAPSHOT + "', it should be defined using 'type.postProcessSnapshot(fn)' instead");
- var action2 = actions[name];
- // apply hook composition
- var baseAction = self[name];
- if (name in Hook && baseAction) {
- var specializedAction_1 = action2;
- action2 = function () {
- baseAction.apply(null, arguments);
- specializedAction_1.apply(null, arguments);
- };
- }
- // the goal of this is to make sure actions using "this" can call themselves,
- // while still allowing the middlewares to register them
- var middlewares = action2.$mst_middleware; // make sure middlewares are not lost
- var boundAction = action2.bind(actions);
- boundAction.$mst_middleware = middlewares;
- var actionInvoker = createActionInvoker(self, name, boundAction);
- actions[name] = actionInvoker;
- (!devMode() ? addHiddenFinalProp : addHiddenWritableProp)(self, name, actionInvoker);
- });
- };
- ModelType.prototype.volatile = function (fn) {
- var _this = this;
- var stateInitializer = function (self) {
- _this.instantiateVolatileState(self, fn(self));
- return self;
- };
- return this.cloneAndEnhance({ initializers: [stateInitializer] });
- };
- ModelType.prototype.instantiateVolatileState = function (self, state) {
- // check views return
- if (!isPlainObject(state))
- throw fail$1("volatile state initializer should return a plain object containing state");
- mobx.set(self, state);
- };
- ModelType.prototype.extend = function (fn) {
- var _this = this;
- var initializer = function (self) {
- var _a = fn(self), actions = _a.actions, views = _a.views, state = _a.state, rest = __rest(_a, ["actions", "views", "state"]);
- for (var key in rest)
- throw fail$1("The `extend` function should return an object with a subset of the fields 'actions', 'views' and 'state'. Found invalid key '" + key + "'");
- if (state)
- _this.instantiateVolatileState(self, state);
- if (views)
- _this.instantiateViews(self, views);
- if (actions)
- _this.instantiateActions(self, actions);
- return self;
- };
- return this.cloneAndEnhance({ initializers: [initializer] });
- };
- ModelType.prototype.views = function (fn) {
- var _this = this;
- var viewInitializer = function (self) {
- _this.instantiateViews(self, fn(self));
- return self;
- };
- return this.cloneAndEnhance({ initializers: [viewInitializer] });
- };
- ModelType.prototype.instantiateViews = function (self, views) {
- // check views return
- if (!isPlainObject(views))
- throw fail$1("views initializer should return a plain object containing views");
- Object.keys(views).forEach(function (key) {
- // is this a computed property?
- var descriptor = Object.getOwnPropertyDescriptor(views, key);
- if ("get" in descriptor) {
- if (mobx.isComputedProp(self, key)) {
- var computedValue = mobx._getAdministration(self, key);
- // TODO: mobx currently does not allow redefining computes yet, pending #1121
- // FIXME: this binds to the internals of mobx!
- computedValue.derivation = descriptor.get;
- computedValue.scope = self;
- if (descriptor.set)
- computedValue.setter = mobx.action(computedValue.name + "-setter", descriptor.set);
- }
- else {
- mobx.computed(self, key, descriptor, true);
- }
- }
- else if (typeof descriptor.value === "function") {
- (!devMode() ? addHiddenFinalProp : addHiddenWritableProp)(self, key, descriptor.value);
- }
- else {
- throw fail$1("A view member should either be a function or getter based property");
- }
- });
- };
- ModelType.prototype.instantiate = function (parent, subpath, environment, initialValue) {
- var value = isStateTreeNode(initialValue)
- ? initialValue
- : this.applySnapshotPreProcessor(initialValue);
- return createObjectNode(this, parent, subpath, environment, value);
- // Optimization: record all prop- view- and action names after first construction, and generate an optimal base class
- // that pre-reserves all these fields for fast object-member lookups
- };
- ModelType.prototype.initializeChildNodes = function (objNode, initialSnapshot) {
- if (initialSnapshot === void 0) { initialSnapshot = {}; }
- var type = objNode.type;
- var result = {};
- type.forAllProps(function (name, childType) {
- result[name] = childType.instantiate(objNode, name, undefined, initialSnapshot[name]);
- });
- return result;
- };
- ModelType.prototype.createNewInstance = function (childNodes) {
- return mobx.observable.object(childNodes, EMPTY_OBJECT, mobxShallow);
- };
- ModelType.prototype.finalizeNewInstance = function (node, instance) {
- addHiddenFinalProp(instance, "toString", objectTypeToString);
- this.forAllProps(function (name) {
- mobx._interceptReads(instance, name, node.unbox);
- });
- this.initializers.reduce(function (self, fn) { return fn(self); }, instance);
- mobx.intercept(instance, this.willChange);
- mobx.observe(instance, this.didChange);
- };
- ModelType.prototype.willChange = function (chg) {
- // TODO: mobx typings don't seem to take into account that newValue can be set even when removing a prop
- var change = chg;
- var node = getStateTreeNode(change.object);
- var subpath = change.name;
- node.assertWritable({ subpath: subpath });
- var childType = node.type.properties[subpath];
- // only properties are typed, state are stored as-is references
- if (childType) {
- typecheckInternal(childType, change.newValue);
- change.newValue = childType.reconcile(node.getChildNode(subpath), change.newValue, node, subpath);
- }
- return change;
- };
- ModelType.prototype.didChange = function (chg) {
- // TODO: mobx typings don't seem to take into account that newValue can be set even when removing a prop
- var change = chg;
- var childNode = getStateTreeNode(change.object);
- var childType = childNode.type.properties[change.name];
- if (!childType) {
- // don't emit patches for volatile state
- return;
- }
- var oldChildValue = change.oldValue ? change.oldValue.snapshot : undefined;
- childNode.emitPatch({
- op: "replace",
- path: escapeJsonPath(change.name),
- value: change.newValue.snapshot,
- oldValue: oldChildValue
- }, childNode);
- };
- ModelType.prototype.getChildren = function (node) {
- var _this = this;
- var res = [];
- this.forAllProps(function (name) {
- res.push(_this.getChildNode(node, name));
- });
- return res;
- };
- ModelType.prototype.getChildNode = function (node, key) {
- if (!(key in this.properties))
- throw fail$1("Not a value property: " + key);
- var childNode = mobx._getAdministration(node.storedValue, key).value; // TODO: blegh!
- if (!childNode)
- throw fail$1("Node not available for property " + key);
- return childNode;
- };
- ModelType.prototype.getSnapshot = function (node, applyPostProcess) {
- var _this = this;
- if (applyPostProcess === void 0) { applyPostProcess = true; }
- var res = {};
- this.forAllProps(function (name, type) {
- mobx.getAtom(node.storedValue, name).reportObserved();
- res[name] = _this.getChildNode(node, name).snapshot;
- });
- if (applyPostProcess) {
- return this.applySnapshotPostProcessor(res);
- }
- return res;
- };
- ModelType.prototype.processInitialSnapshot = function (childNodes) {
- var processed = {};
- Object.keys(childNodes).forEach(function (key) {
- processed[key] = childNodes[key].getSnapshot();
- });
- return this.applySnapshotPostProcessor(processed);
- };
- ModelType.prototype.applyPatchLocally = function (node, subpath, patch) {
- if (!(patch.op === "replace" || patch.op === "add")) {
- throw fail$1("object does not support operation " + patch.op);
- }
- node.storedValue[subpath] = patch.value;
- };
- ModelType.prototype.applySnapshot = function (node, snapshot) {
- var preProcessedSnapshot = this.applySnapshotPreProcessor(snapshot);
- typecheckInternal(this, preProcessedSnapshot);
- this.forAllProps(function (name) {
- node.storedValue[name] = preProcessedSnapshot[name];
- });
- };
- ModelType.prototype.applySnapshotPreProcessor = function (snapshot) {
- var processor = this.preProcessor;
- return processor ? processor.call(null, snapshot) : snapshot;
- };
- ModelType.prototype.applySnapshotPostProcessor = function (snapshot) {
- var postProcessor = this.postProcessor;
- if (postProcessor)
- return postProcessor.call(null, snapshot);
- return snapshot;
- };
- ModelType.prototype.getChildType = function (propertyName) {
- assertIsString(propertyName, 1);
- return this.properties[propertyName];
- };
- ModelType.prototype.isValidSnapshot = function (value, context) {
- var _this = this;
- var snapshot = this.applySnapshotPreProcessor(value);
- if (!isPlainObject(snapshot)) {
- return typeCheckFailure(context, snapshot, "Value is not a plain object");
- }
- return flattenTypeErrors(this.propertyNames.map(function (key) {
- return _this.properties[key].validate(snapshot[key], getContextForPath(context, key, _this.properties[key]));
- }));
- };
- ModelType.prototype.forAllProps = function (fn) {
- var _this = this;
- this.propertyNames.forEach(function (key) { return fn(key, _this.properties[key]); });
- };
- ModelType.prototype.describe = function () {
- var _this = this;
- // optimization: cache
- return ("{ " +
- this.propertyNames.map(function (key) { return key + ": " + _this.properties[key].describe(); }).join("; ") +
- " }");
- };
- ModelType.prototype.getDefaultSnapshot = function () {
- return EMPTY_OBJECT;
- };
- ModelType.prototype.removeChild = function (node, subpath) {
- node.storedValue[subpath] = undefined;
- };
- __decorate([
- mobx.action
- ], ModelType.prototype, "applySnapshot", null);
- return ModelType;
- }(ComplexType));
- /**
- * `types.model` - Creates a new model type by providing a name, properties, volatile state and actions.
- *
- * See the [model type](https://github.com/mobxjs/mobx-state-tree#creating-models) description or the [getting started](https://github.com/mobxjs/mobx-state-tree/blob/master/docs/getting-started.md#getting-started-1) tutorial.
- */
- function model() {
- var args = [];
- for (var _i = 0; _i < arguments.length; _i++) {
- args[_i] = arguments[_i];
- }
- var name = typeof args[0] === "string" ? args.shift() : "AnonymousModel";
- var properties = args.shift() || {};
- return new ModelType({ name: name, properties: properties });
- }
- /**
- * `types.compose` - Composes a new model from one or more existing model types.
- * This method can be invoked in two forms:
- * Given 2 or more model types, the types are composed into a new Type.
- * Given first parameter as a string and 2 or more model types,
- * the types are composed into a new Type with the given name
- */
- function compose() {
- var args = [];
- for (var _i = 0; _i < arguments.length; _i++) {
- args[_i] = arguments[_i];
- }
- // TODO: just join the base type names if no name is provided
- var hasTypename = typeof args[0] === "string";
- var typeName = hasTypename ? args[0] : "AnonymousModel";
- if (hasTypename) {
- args.shift();
- }
- // check all parameters
- if (devMode()) {
- args.forEach(function (type, i) {
- assertArg(type, isModelType, "mobx-state-tree model type", hasTypename ? i + 2 : i + 1);
- });
- }
- return args
- .reduce(function (prev, cur) {
- return prev.cloneAndEnhance({
- name: prev.name + "_" + cur.name,
- properties: cur.properties,
- initializers: cur.initializers,
- preProcessor: function (snapshot) {
- return cur.applySnapshotPreProcessor(prev.applySnapshotPreProcessor(snapshot));
- },
- postProcessor: function (snapshot) {
- return cur.applySnapshotPostProcessor(prev.applySnapshotPostProcessor(snapshot));
- }
- });
- })
- .named(typeName);
- }
- /**
- * Returns if a given value represents a model type.
- *
- * @param type
- * @returns
- */
- function isModelType(type) {
- return isType(type) && (type.flags & TypeFlags.Object) > 0;
- }
- // TODO: implement CoreType using types.custom ?
- /**
- * @internal
- * @hidden
- */
- var CoreType = /** @class */ (function (_super) {
- __extends(CoreType, _super);
- function CoreType(name, flags, checker, initializer) {
- if (initializer === void 0) { initializer = identity; }
- var _this = _super.call(this, name) || this;
- _this.flags = flags;
- _this.checker = checker;
- _this.initializer = initializer;
- _this.flags = flags;
- return _this;
- }
- CoreType.prototype.describe = function () {
- return this.name;
- };
- CoreType.prototype.instantiate = function (parent, subpath, environment, initialValue) {
- return createScalarNode(this, parent, subpath, environment, initialValue);
- };
- CoreType.prototype.createNewInstance = function (snapshot) {
- return this.initializer(snapshot);
- };
- CoreType.prototype.isValidSnapshot = function (value, context) {
- if (isPrimitive(value) && this.checker(value)) {
- return typeCheckSuccess();
- }
- var typeName = this.name === "Date" ? "Date or a unix milliseconds timestamp" : this.name;
- return typeCheckFailure(context, value, "Value is not a " + typeName);
- };
- return CoreType;
- }(SimpleType));
- /**
- * `types.string` - Creates a type that can only contain a string value.
- * This type is used for string values by default
- *
- * Example:
- * ```ts
- * const Person = types.model({
- * firstName: types.string,
- * lastName: "Doe"
- * })
- * ```
- */
- // tslint:disable-next-line:variable-name
- var string = new CoreType("string", TypeFlags.String, function (v) { return typeof v === "string"; });
- /**
- * `types.number` - Creates a type that can only contain a numeric value.
- * This type is used for numeric values by default
- *
- * Example:
- * ```ts
- * const Vector = types.model({
- * x: types.number,
- * y: 1.5
- * })
- * ```
- */
- // tslint:disable-next-line:variable-name
- var number = new CoreType("number", TypeFlags.Number, function (v) { return typeof v === "number"; });
- /**
- * `types.integer` - Creates a type that can only contain an integer value.
- * This type is used for integer values by default
- *
- * Example:
- * ```ts
- * const Size = types.model({
- * width: types.integer,
- * height: 10
- * })
- * ```
- */
- // tslint:disable-next-line:variable-name
- var integer = new CoreType("integer", TypeFlags.Integer, function (v) { return isInteger(v); });
- /**
- * `types.boolean` - Creates a type that can only contain a boolean value.
- * This type is used for boolean values by default
- *
- * Example:
- * ```ts
- * const Thing = types.model({
- * isCool: types.boolean,
- * isAwesome: false
- * })
- * ```
- */
- // tslint:disable-next-line:variable-name
- var boolean = new CoreType("boolean", TypeFlags.Boolean, function (v) { return typeof v === "boolean"; });
- /**
- * `types.null` - The type of the value `null`
- */
- var nullType = new CoreType("null", TypeFlags.Null, function (v) { return v === null; });
- /**
- * `types.undefined` - The type of the value `undefined`
- */
- var undefinedType = new CoreType("undefined", TypeFlags.Undefined, function (v) { return v === undefined; });
- var _DatePrimitive = new CoreType("Date", TypeFlags.Date, function (v) { return typeof v === "number" || v instanceof Date; }, function (v) { return (v instanceof Date ? v : new Date(v)); });
- _DatePrimitive.getSnapshot = function (node) {
- return node.storedValue.getTime();
- };
- /**
- * `types.Date` - Creates a type that can only contain a javascript Date value.
- *
- * Example:
- * ```ts
- * const LogLine = types.model({
- * timestamp: types.Date,
- * })
- *
- * LogLine.create({ timestamp: new Date() })
- * ```
- */
- var DatePrimitive = _DatePrimitive;
- /**
- * @internal
- * @hidden
- */
- function getPrimitiveFactoryFromValue(value) {
- switch (typeof value) {
- case "string":
- return string;
- case "number":
- return number; // In the future, isInteger(value) ? integer : number would be interesting, but would be too breaking for now
- case "boolean":
- return boolean;
- case "object":
- if (value instanceof Date)
- return DatePrimitive;
- }
- throw fail$1("Cannot determine primitive type from value " + value);
- }
- /**
- * Returns if a given value represents a primitive type.
- *
- * @param type
- * @returns
- */
- function isPrimitiveType(type) {
- return (isType(type) &&
- (type.flags &
- (TypeFlags.String |
- TypeFlags.Number |
- TypeFlags.Integer |
- TypeFlags.Boolean |
- TypeFlags.Date)) >
- 0);
- }
- /**
- * @internal
- * @hidden
- */
- var Literal = /** @class */ (function (_super) {
- __extends(Literal, _super);
- function Literal(value) {
- var _this = _super.call(this, JSON.stringify(value)) || this;
- _this.flags = TypeFlags.Literal;
- _this.value = value;
- return _this;
- }
- Literal.prototype.instantiate = function (parent, subpath, environment, initialValue) {
- return createScalarNode(this, parent, subpath, environment, initialValue);
- };
- Literal.prototype.describe = function () {
- return JSON.stringify(this.value);
- };
- Literal.prototype.isValidSnapshot = function (value, context) {
- if (isPrimitive(value) && value === this.value) {
- return typeCheckSuccess();
- }
- return typeCheckFailure(context, value, "Value is not a literal " + JSON.stringify(this.value));
- };
- return Literal;
- }(SimpleType));
- /**
- * `types.literal` - The literal type will return a type that will match only the exact given type.
- * The given value must be a primitive, in order to be serialized to a snapshot correctly.
- * You can use literal to match exact strings for example the exact male or female string.
- *
- * Example:
- * ```ts
- * const Person = types.model({
- * name: types.string,
- * gender: types.union(types.literal('male'), types.literal('female'))
- * })
- * ```
- *
- * @param value The value to use in the strict equal check
- * @returns
- */
- function literal(value) {
- // check that the given value is a primitive
- assertArg(value, isPrimitive, "primitive", 1);
- return new Literal(value);
- }
- /**
- * Returns if a given value represents a literal type.
- *
- * @param type
- * @returns
- */
- function isLiteralType(type) {
- return isType(type) && (type.flags & TypeFlags.Literal) > 0;
- }
- var Refinement = /** @class */ (function (_super) {
- __extends(Refinement, _super);
- function Refinement(name, _subtype, _predicate, _message) {
- var _this = _super.call(this, name) || this;
- _this._subtype = _subtype;
- _this._predicate = _predicate;
- _this._message = _message;
- return _this;
- }
- Object.defineProperty(Refinement.prototype, "flags", {
- get: function () {
- return this._subtype.flags | TypeFlags.Refinement;
- },
- enumerable: true,
- configurable: true
- });
- Refinement.prototype.describe = function () {
- return this.name;
- };
- Refinement.prototype.instantiate = function (parent, subpath, environment, initialValue) {
- // create the child type
- return this._subtype.instantiate(parent, subpath, environment, initialValue);
- };
- Refinement.prototype.isAssignableFrom = function (type) {
- return this._subtype.isAssignableFrom(type);
- };
- Refinement.prototype.isValidSnapshot = function (value, context) {
- var subtypeErrors = this._subtype.validate(value, context);
- if (subtypeErrors.length > 0)
- return subtypeErrors;
- var snapshot = isStateTreeNode(value) ? getStateTreeNode(value).snapshot : value;
- if (!this._predicate(snapshot)) {
- return typeCheckFailure(context, value, this._message(value));
- }
- return typeCheckSuccess();
- };
- Refinement.prototype.reconcile = function (current, newValue, parent, subpath) {
- return this._subtype.reconcile(current, newValue, parent, subpath);
- };
- Refinement.prototype.getSubTypes = function () {
- return this._subtype;
- };
- return Refinement;
- }(BaseType));
- /**
- * `types.refinement` - Creates a type that is more specific than the base type, e.g. `types.refinement(types.string, value => value.length > 5)` to create a type of strings that can only be longer then 5.
- *
- * @param name
- * @param type
- * @param predicate
- * @returns
- */
- function refinement() {
- var args = [];
- for (var _i = 0; _i < arguments.length; _i++) {
- args[_i] = arguments[_i];
- }
- var name = typeof args[0] === "string" ? args.shift() : isType(args[0]) ? args[0].name : null;
- var type = args[0];
- var predicate = args[1];
- var message = args[2]
- ? args[2]
- : function (v) { return "Value does not respect the refinement predicate"; };
- // ensures all parameters are correct
- assertIsType(type, [1, 2]);
- assertIsString(name, 1);
- assertIsFunction(predicate, [2, 3]);
- assertIsFunction(message, [3, 4]);
- return new Refinement(name, type, predicate, message);
- }
- /**
- * Returns if a given value is a refinement type.
- *
- * @param type
- * @returns
- */
- function isRefinementType(type) {
- return (type.flags & TypeFlags.Refinement) > 0;
- }
- /**
- * `types.enumeration` - Can be used to create an string based enumeration.
- * (note: this methods is just sugar for a union of string literals)
- *
- * Example:
- * ```ts
- * const TrafficLight = types.model({
- * color: types.enumeration("Color", ["Red", "Orange", "Green"])
- * })
- * ```
- *
- * @param name descriptive name of the enumeration (optional)
- * @param options possible values this enumeration can have
- * @returns
- */
- function enumeration(name, options) {
- var realOptions = typeof name === "string" ? options : name;
- // check all options
- if (devMode()) {
- realOptions.forEach(function (option, i) {
- assertIsString(option, i + 1);
- });
- }
- var type = union.apply(void 0, __spread(realOptions.map(function (option) { return literal("" + option); })));
- if (typeof name === "string")
- type.name = name;
- return type;
- }
- /**
- * @internal
- * @hidden
- */
- var Union = /** @class */ (function (_super) {
- __extends(Union, _super);
- function Union(name, _types, options) {
- var _this = _super.call(this, name) || this;
- _this._types = _types;
- _this._eager = true;
- options = __assign({ eager: true, dispatcher: undefined }, options);
- _this._dispatcher = options.dispatcher;
- if (!options.eager)
- _this._eager = false;
- return _this;
- }
- Object.defineProperty(Union.prototype, "flags", {
- get: function () {
- var result = TypeFlags.Union;
- this._types.forEach(function (type) {
- result |= type.flags;
- });
- return result;
- },
- enumerable: true,
- configurable: true
- });
- Union.prototype.isAssignableFrom = function (type) {
- return this._types.some(function (subType) { return subType.isAssignableFrom(type); });
- };
- Union.prototype.describe = function () {
- return "(" + this._types.map(function (factory) { return factory.describe(); }).join(" | ") + ")";
- };
- Union.prototype.instantiate = function (parent, subpath, environment, initialValue) {
- var type = this.determineType(initialValue, undefined);
- if (!type)
- throw fail$1("No matching type for union " + this.describe()); // can happen in prod builds
- return type.instantiate(parent, subpath, environment, initialValue);
- };
- Union.prototype.reconcile = function (current, newValue, parent, subpath) {
- var type = this.determineType(newValue, current.type);
- if (!type)
- throw fail$1("No matching type for union " + this.describe()); // can happen in prod builds
- return type.reconcile(current, newValue, parent, subpath);
- };
- Union.prototype.determineType = function (value, reconcileCurrentType) {
- // try the dispatcher, if defined
- if (this._dispatcher) {
- return this._dispatcher(value);
- }
- // find the most accomodating type
- // if we are using reconciliation try the current node type first (fix for #1045)
- if (reconcileCurrentType) {
- if (reconcileCurrentType.is(value)) {
- return reconcileCurrentType;
- }
- return this._types.filter(function (t) { return t !== reconcileCurrentType; }).find(function (type) { return type.is(value); });
- }
- else {
- return this._types.find(function (type) { return type.is(value); });
- }
- };
- Union.prototype.isValidSnapshot = function (value, context) {
- if (this._dispatcher) {
- return this._dispatcher(value).validate(value, context);
- }
- var allErrors = [];
- var applicableTypes = 0;
- for (var i = 0; i < this._types.length; i++) {
- var type = this._types[i];
- var errors = type.validate(value, context);
- if (errors.length === 0) {
- if (this._eager)
- return typeCheckSuccess();
- else
- applicableTypes++;
- }
- else {
- allErrors.push(errors);
- }
- }
- if (applicableTypes === 1)
- return typeCheckSuccess();
- return typeCheckFailure(context, value, "No type is applicable for the union").concat(flattenTypeErrors(allErrors));
- };
- Union.prototype.getSubTypes = function () {
- return this._types;
- };
- return Union;
- }(BaseType));
- /**
- * `types.union` - Create a union of multiple types. If the correct type cannot be inferred unambiguously from a snapshot, provide a dispatcher function of the form `(snapshot) => Type`.
- *
- * @param optionsOrType
- * @param otherTypes
- * @returns
- */
- function union(optionsOrType) {
- var otherTypes = [];
- for (var _i = 1; _i < arguments.length; _i++) {
- otherTypes[_i - 1] = arguments[_i];
- }
- var options = isType(optionsOrType) ? undefined : optionsOrType;
- var types = isType(optionsOrType) ? __spread([optionsOrType], otherTypes) : otherTypes;
- var name = "(" + types.map(function (type) { return type.name; }).join(" | ") + ")";
- // check all options
- if (devMode()) {
- if (options) {
- assertArg(options, function (o) { return isPlainObject(o); }, "object { eager?: boolean, dispatcher?: Function }", 1);
- }
- types.forEach(function (type, i) {
- assertIsType(type, options ? i + 2 : i + 1);
- });
- }
- return new Union(name, types, options);
- }
- /**
- * Returns if a given value represents a union type.
- *
- * @param type
- * @returns
- */
- function isUnionType(type) {
- return (type.flags & TypeFlags.Union) > 0;
- }
- /**
- * @hidden
- * @internal
- */
- var OptionalValue = /** @class */ (function (_super) {
- __extends(OptionalValue, _super);
- function OptionalValue(_subtype, _defaultValue, optionalValues) {
- var _this = _super.call(this, _subtype.name) || this;
- _this._subtype = _subtype;
- _this._defaultValue = _defaultValue;
- _this.optionalValues = optionalValues;
- return _this;
- }
- Object.defineProperty(OptionalValue.prototype, "flags", {
- get: function () {
- return this._subtype.flags | TypeFlags.Optional;
- },
- enumerable: true,
- configurable: true
- });
- OptionalValue.prototype.describe = function () {
- return this._subtype.describe() + "?";
- };
- OptionalValue.prototype.instantiate = function (parent, subpath, environment, initialValue) {
- if (this.optionalValues.indexOf(initialValue) >= 0) {
- var defaultInstanceOrSnapshot = this.getDefaultInstanceOrSnapshot();
- return this._subtype.instantiate(parent, subpath, environment, defaultInstanceOrSnapshot);
- }
- return this._subtype.instantiate(parent, subpath, environment, initialValue);
- };
- OptionalValue.prototype.reconcile = function (current, newValue, parent, subpath) {
- return this._subtype.reconcile(current, this.optionalValues.indexOf(newValue) < 0 && this._subtype.is(newValue)
- ? newValue
- : this.getDefaultInstanceOrSnapshot(), parent, subpath);
- };
- OptionalValue.prototype.getDefaultInstanceOrSnapshot = function () {
- var defaultInstanceOrSnapshot = typeof this._defaultValue === "function"
- ? this._defaultValue()
- : this._defaultValue;
- // while static values are already snapshots and checked on types.optional
- // generator functions must always be rechecked just in case
- if (typeof this._defaultValue === "function") {
- typecheckInternal(this, defaultInstanceOrSnapshot);
- }
- return defaultInstanceOrSnapshot;
- };
- OptionalValue.prototype.isValidSnapshot = function (value, context) {
- // defaulted values can be skipped
- if (this.optionalValues.indexOf(value) >= 0) {
- return typeCheckSuccess();
- }
- // bounce validation to the sub-type
- return this._subtype.validate(value, context);
- };
- OptionalValue.prototype.isAssignableFrom = function (type) {
- return this._subtype.isAssignableFrom(type);
- };
- OptionalValue.prototype.getSubTypes = function () {
- return this._subtype;
- };
- return OptionalValue;
- }(BaseType));
- function checkOptionalPreconditions(type, defaultValueOrFunction) {
- // make sure we never pass direct instances
- if (typeof defaultValueOrFunction !== "function" && isStateTreeNode(defaultValueOrFunction)) {
- throw fail$1("default value cannot be an instance, pass a snapshot or a function that creates an instance/snapshot instead");
- }
- assertIsType(type, 1);
- if (devMode()) {
- // we only check default values if they are passed directly
- // if they are generator functions they will be checked once they are generated
- // we don't check generator function results here to avoid generating a node just for type-checking purposes
- // which might generate side-effects
- if (typeof defaultValueOrFunction !== "function") {
- typecheckInternal(type, defaultValueOrFunction);
- }
- }
- }
- /**
- * `types.optional` - Can be used to create a property with a default value.
- *
- * Depending on the third argument (`optionalValues`) there are two ways of operation:
- * - If the argument is not provided, then if a value is not provided in the snapshot (`undefined` or missing),
- * it will default to the provided `defaultValue`
- * - If the argument is provided, then if the value in the snapshot matches one of the optional values inside the array then it will
- * default to the provided `defaultValue`. Additionally, if one of the optional values inside the array is `undefined` then a missing
- * property is also valid.
- *
- * Note that it is also possible to include values of the same type as the intended subtype as optional values,
- * in this case the optional value will be transformed into the `defaultValue` (e.g. `types.optional(types.string, "unnamed", [undefined, ""])`
- * will transform the snapshot values `undefined` (and therefore missing) and empty strings into the string `"unnamed"` when it gets
- * instantiated).
- *
- * If `defaultValue` is a function, the function will be invoked for every new instance.
- * Applying a snapshot in which the optional value is one of the optional values (or `undefined`/_not_ present if none are provided) causes the
- * value to be reset.
- *
- * Example:
- * ```ts
- * const Todo = types.model({
- * title: types.string,
- * subtitle1: types.optional(types.string, "", [null]),
- * subtitle2: types.optional(types.string, "", [null, undefined]),
- * done: types.optional(types.boolean, false),
- * created: types.optional(types.Date, () => new Date()),
- * })
- *
- * // if done is missing / undefined it will become false
- * // if created is missing / undefined it will get a freshly generated timestamp
- * // if subtitle1 is null it will default to "", but it cannot be missing or undefined
- * // if subtitle2 is null or undefined it will default to ""; since it can be undefined it can also be missing
- * const todo = Todo.create({ title: "Get coffee", subtitle1: null })
- * ```
- *
- * @param type
- * @param defaultValueOrFunction
- * @param optionalValues an optional array with zero or more primitive values (string, number, boolean, null or undefined)
- * that will be converted into the default. `[ undefined ]` is assumed when none is provided
- * @returns
- */
- function optional(type, defaultValueOrFunction, optionalValues) {
- checkOptionalPreconditions(type, defaultValueOrFunction);
- return new OptionalValue(type, defaultValueOrFunction, optionalValues ? optionalValues : undefinedAsOptionalValues);
- }
- var undefinedAsOptionalValues = [undefined];
- /**
- * Returns if a value represents an optional type.
- *
- * @template IT
- * @param type
- * @returns
- */
- function isOptionalType(type) {
- return isType(type) && (type.flags & TypeFlags.Optional) > 0;
- }
- var optionalUndefinedType = optional(undefinedType, undefined);
- var optionalNullType = optional(nullType, null);
- /**
- * `types.maybe` - Maybe will make a type nullable, and also optional.
- * The value `undefined` will be used to represent nullability.
- *
- * @param type
- * @returns
- */
- function maybe(type) {
- assertIsType(type, 1);
- return union(type, optionalUndefinedType);
- }
- /**
- * `types.maybeNull` - Maybe will make a type nullable, and also optional.
- * The value `null` will be used to represent no value.
- *
- * @param type
- * @returns
- */
- function maybeNull(type) {
- assertIsType(type, 1);
- return union(type, optionalNullType);
- }
- var Late = /** @class */ (function (_super) {
- __extends(Late, _super);
- function Late(name, _definition) {
- var _this = _super.call(this, name) || this;
- _this._definition = _definition;
- return _this;
- }
- Object.defineProperty(Late.prototype, "flags", {
- get: function () {
- return (this._subType ? this._subType.flags : 0) | TypeFlags.Late;
- },
- enumerable: true,
- configurable: true
- });
- Late.prototype.getSubType = function (mustSucceed) {
- if (!this._subType) {
- var t = undefined;
- try {
- t = this._definition();
- }
- catch (e) {
- if (e instanceof ReferenceError)
- // can happen in strict ES5 code when a definition is self refering
- t = undefined;
- else
- throw e;
- }
- if (mustSucceed && t === undefined)
- throw fail$1("Late type seems to be used too early, the definition (still) returns undefined");
- if (t) {
- if (devMode() && !isType(t))
- throw fail$1("Failed to determine subtype, make sure types.late returns a type definition.");
- this._subType = t;
- }
- }
- return this._subType;
- };
- Late.prototype.instantiate = function (parent, subpath, environment, initialValue) {
- return this.getSubType(true).instantiate(parent, subpath, environment, initialValue);
- };
- Late.prototype.reconcile = function (current, newValue, parent, subpath) {
- return this.getSubType(true).reconcile(current, newValue, parent, subpath);
- };
- Late.prototype.describe = function () {
- var t = this.getSubType(false);
- return t ? t.name : "<uknown late type>";
- };
- Late.prototype.isValidSnapshot = function (value, context) {
- var t = this.getSubType(false);
- if (!t) {
- // See #916; the variable the definition closure is pointing to wasn't defined yet, so can't be evaluted yet here
- return typeCheckSuccess();
- }
- return t.validate(value, context);
- };
- Late.prototype.isAssignableFrom = function (type) {
- var t = this.getSubType(false);
- return t ? t.isAssignableFrom(type) : false;
- };
- Late.prototype.getSubTypes = function () {
- var subtype = this.getSubType(false);
- return subtype ? subtype : cannotDetermineSubtype;
- };
- return Late;
- }(BaseType));
- /**
- * `types.late` - Defines a type that gets implemented later. This is useful when you have to deal with circular dependencies.
- * Please notice that when defining circular dependencies TypeScript isn't smart enough to inference them.
- *
- * Example:
- * ```ts
- * // TypeScript isn't smart enough to infer self referencing types.
- * const Node = types.model({
- * children: types.array(types.late((): IAnyModelType => Node)) // then typecast each array element to Instance<typeof Node>
- * })
- * ```
- *
- * @param name The name to use for the type that will be returned.
- * @param type A function that returns the type that will be defined.
- * @returns
- */
- function late(nameOrType, maybeType) {
- var name = typeof nameOrType === "string" ? nameOrType : "late(" + nameOrType.toString() + ")";
- var type = typeof nameOrType === "string" ? maybeType : nameOrType;
- // checks that the type is actually a late type
- if (devMode()) {
- if (!(typeof type === "function" && type.length === 0))
- throw fail$1("Invalid late type, expected a function with zero arguments that returns a type, got: " +
- type);
- }
- return new Late(name, type);
- }
- /**
- * Returns if a given value represents a late type.
- *
- * @param type
- * @returns
- */
- function isLateType(type) {
- return isType(type) && (type.flags & TypeFlags.Late) > 0;
- }
- /**
- * @internal
- * @hidden
- */
- var Frozen = /** @class */ (function (_super) {
- __extends(Frozen, _super);
- function Frozen(subType) {
- var _this = _super.call(this, subType ? "frozen(" + subType.name + ")" : "frozen") || this;
- _this.subType = subType;
- _this.flags = TypeFlags.Frozen;
- return _this;
- }
- Frozen.prototype.describe = function () {
- return "<any immutable value>";
- };
- Frozen.prototype.instantiate = function (parent, subpath, environment, value) {
- // create the node
- return createScalarNode(this, parent, subpath, environment, deepFreeze(value));
- };
- Frozen.prototype.isValidSnapshot = function (value, context) {
- if (!isSerializable(value)) {
- return typeCheckFailure(context, value, "Value is not serializable and cannot be frozen");
- }
- if (this.subType)
- return this.subType.validate(value, context);
- return typeCheckSuccess();
- };
- return Frozen;
- }(SimpleType));
- var untypedFrozenInstance = new Frozen();
- /**
- * `types.frozen` - Frozen can be used to store any value that is serializable in itself (that is valid JSON).
- * Frozen values need to be immutable or treated as if immutable. They need be serializable as well.
- * Values stored in frozen will snapshotted as-is by MST, and internal changes will not be tracked.
- *
- * This is useful to store complex, but immutable values like vectors etc. It can form a powerful bridge to parts of your application that should be immutable, or that assume data to be immutable.
- *
- * Note: if you want to store free-form state that is mutable, or not serializeable, consider using volatile state instead.
- *
- * Frozen properties can be defined in three different ways
- * 1. `types.frozen(SubType)` - provide a valid MST type and frozen will check if the provided data conforms the snapshot for that type
- * 2. `types.frozen({ someDefaultValue: true})` - provide a primitive value, object or array, and MST will infer the type from that object, and also make it the default value for the field
- * 3. `types.frozen<TypeScriptType>()` - provide a typescript type, to help in strongly typing the field (design time only)
- *
- * Example:
- * ```ts
- * const GameCharacter = types.model({
- * name: string,
- * location: types.frozen({ x: 0, y: 0})
- * })
- *
- * const hero = GameCharacter.create({
- * name: "Mario",
- * location: { x: 7, y: 4 }
- * })
- *
- * hero.location = { x: 10, y: 2 } // OK
- * hero.location.x = 7 // Not ok!
- * ```
- *
- * ```ts
- * type Point = { x: number, y: number }
- * const Mouse = types.model({
- * loc: types.frozen<Point>()
- * })
- * ```
- *
- * @param defaultValueOrType
- * @returns
- */
- function frozen(arg) {
- if (arguments.length === 0)
- return untypedFrozenInstance;
- else if (isType(arg))
- return new Frozen(arg);
- else
- return optional(untypedFrozenInstance, arg);
- }
- /**
- * Returns if a given value represents a frozen type.
- *
- * @param type
- * @returns
- */
- function isFrozenType(type) {
- return isType(type) && (type.flags & TypeFlags.Frozen) > 0;
- }
- function getInvalidationCause(hook) {
- switch (hook) {
- case Hook.beforeDestroy:
- return "destroy";
- case Hook.beforeDetach:
- return "detach";
- default:
- return undefined;
- }
- }
- var StoredReference = /** @class */ (function () {
- function StoredReference(value, targetType) {
- this.targetType = targetType;
- if (isValidIdentifier(value)) {
- this.identifier = value;
- }
- else if (isStateTreeNode(value)) {
- var targetNode = getStateTreeNode(value);
- if (!targetNode.identifierAttribute)
- throw fail$1("Can only store references with a defined identifier attribute.");
- var id = targetNode.unnormalizedIdentifier;
- if (id === null || id === undefined) {
- throw fail$1("Can only store references to tree nodes with a defined identifier.");
- }
- this.identifier = id;
- }
- else {
- throw fail$1("Can only store references to tree nodes or identifiers, got: '" + value + "'");
- }
- }
- StoredReference.prototype.updateResolvedReference = function (node) {
- var normalizedId = normalizeIdentifier(this.identifier);
- var root = node.root;
- var lastCacheModification = root.identifierCache.getLastCacheModificationPerId(normalizedId);
- if (!this.resolvedReference ||
- this.resolvedReference.lastCacheModification !== lastCacheModification) {
- var targetType = this.targetType;
- // reference was initialized with the identifier of the target
- var target = root.identifierCache.resolve(targetType, normalizedId);
- if (!target) {
- throw new InvalidReferenceError("[mobx-state-tree] Failed to resolve reference '" + this.identifier + "' to type '" + this.targetType.name + "' (from node: " + node.path + ")");
- }
- this.resolvedReference = {
- node: target,
- lastCacheModification: lastCacheModification
- };
- }
- };
- Object.defineProperty(StoredReference.prototype, "resolvedValue", {
- get: function () {
- this.updateResolvedReference(this.node);
- return this.resolvedReference.node.value;
- },
- enumerable: true,
- configurable: true
- });
- return StoredReference;
- }());
- /**
- * @internal
- * @hidden
- */
- var InvalidReferenceError = /** @class */ (function (_super) {
- __extends(InvalidReferenceError, _super);
- function InvalidReferenceError(m) {
- var _this = _super.call(this, m) || this;
- Object.setPrototypeOf(_this, InvalidReferenceError.prototype);
- return _this;
- }
- return InvalidReferenceError;
- }(Error));
- /**
- * @internal
- * @hidden
- */
- var BaseReferenceType = /** @class */ (function (_super) {
- __extends(BaseReferenceType, _super);
- function BaseReferenceType(targetType, onInvalidated) {
- var _this = _super.call(this, "reference(" + targetType.name + ")") || this;
- _this.targetType = targetType;
- _this.onInvalidated = onInvalidated;
- _this.flags = TypeFlags.Reference;
- return _this;
- }
- BaseReferenceType.prototype.describe = function () {
- return this.name;
- };
- BaseReferenceType.prototype.isAssignableFrom = function (type) {
- return this.targetType.isAssignableFrom(type);
- };
- BaseReferenceType.prototype.isValidSnapshot = function (value, context) {
- return isValidIdentifier(value)
- ? typeCheckSuccess()
- : typeCheckFailure(context, value, "Value is not a valid identifier, which is a string or a number");
- };
- BaseReferenceType.prototype.fireInvalidated = function (cause, storedRefNode, referenceId, refTargetNode) {
- // to actually invalidate a reference we need an alive parent,
- // since it is a scalar value (immutable-ish) and we need to change it
- // from the parent
- var storedRefParentNode = storedRefNode.parent;
- if (!storedRefParentNode || !storedRefParentNode.isAlive) {
- return;
- }
- var storedRefParentValue = storedRefParentNode.storedValue;
- if (!storedRefParentValue) {
- return;
- }
- this.onInvalidated({
- cause: cause,
- parent: storedRefParentValue,
- invalidTarget: refTargetNode ? refTargetNode.storedValue : undefined,
- invalidId: referenceId,
- replaceRef: function (newRef) {
- applyPatch(storedRefNode.root.storedValue, {
- op: "replace",
- value: newRef,
- path: storedRefNode.path
- });
- },
- removeRef: function () {
- if (isModelType(storedRefParentNode.type)) {
- this.replaceRef(undefined);
- }
- else {
- applyPatch(storedRefNode.root.storedValue, {
- op: "remove",
- path: storedRefNode.path
- });
- }
- }
- });
- };
- BaseReferenceType.prototype.addTargetNodeWatcher = function (storedRefNode, referenceId) {
- var _this = this;
- // this will make sure the target node becomes created
- var refTargetValue = this.getValue(storedRefNode);
- if (!refTargetValue) {
- return undefined;
- }
- var refTargetNode = getStateTreeNode(refTargetValue);
- var hookHandler = function (_, refTargetNodeHook) {
- var cause = getInvalidationCause(refTargetNodeHook);
- if (!cause) {
- return;
- }
- _this.fireInvalidated(cause, storedRefNode, referenceId, refTargetNode);
- };
- var refTargetDetachHookDisposer = refTargetNode.registerHook(Hook.beforeDetach, hookHandler);
- var refTargetDestroyHookDisposer = refTargetNode.registerHook(Hook.beforeDestroy, hookHandler);
- return function () {
- refTargetDetachHookDisposer();
- refTargetDestroyHookDisposer();
- };
- };
- BaseReferenceType.prototype.watchTargetNodeForInvalidations = function (storedRefNode, identifier, customGetSet) {
- var _this = this;
- if (!this.onInvalidated) {
- return;
- }
- var onRefTargetDestroyedHookDisposer;
- // get rid of the watcher hook when the stored ref node is destroyed
- // detached is ignored since scalar nodes (where the reference resides) cannot be detached
- storedRefNode.registerHook(Hook.beforeDestroy, function () {
- if (onRefTargetDestroyedHookDisposer) {
- onRefTargetDestroyedHookDisposer();
- }
- });
- var startWatching = function (sync) {
- // re-create hook in case the stored ref gets reattached
- if (onRefTargetDestroyedHookDisposer) {
- onRefTargetDestroyedHookDisposer();
- }
- // make sure the target node is actually there and initialized
- var storedRefParentNode = storedRefNode.parent;
- var storedRefParentValue = storedRefParentNode && storedRefParentNode.storedValue;
- if (storedRefParentNode && storedRefParentNode.isAlive && storedRefParentValue) {
- var refTargetNodeExists = void 0;
- if (customGetSet) {
- refTargetNodeExists = !!customGetSet.get(identifier, storedRefParentValue);
- }
- else {
- refTargetNodeExists = storedRefNode.root.identifierCache.has(_this.targetType, normalizeIdentifier(identifier));
- }
- if (!refTargetNodeExists) {
- // we cannot change the reference in sync mode
- // since we are in the middle of a reconciliation/instantiation and the change would be overwritten
- // for those cases just let the wrong reference be assigned and fail upon usage
- // (like current references do)
- // this means that effectively this code will only run when it is created from a snapshot
- if (!sync) {
- _this.fireInvalidated("invalidSnapshotReference", storedRefNode, identifier, null);
- }
- }
- else {
- onRefTargetDestroyedHookDisposer = _this.addTargetNodeWatcher(storedRefNode, identifier);
- }
- }
- };
- if (storedRefNode.state === NodeLifeCycle.FINALIZED) {
- // already attached, so the whole tree is ready
- startWatching(true);
- }
- else {
- if (!storedRefNode.isRoot) {
- // start watching once the whole tree is ready
- storedRefNode.root.registerHook(Hook.afterCreationFinalization, function () {
- // make sure to attach it so it can start listening
- if (storedRefNode.parent) {
- storedRefNode.parent.createObservableInstanceIfNeeded();
- }
- });
- }
- // start watching once the node is attached somewhere / parent changes
- storedRefNode.registerHook(Hook.afterAttach, function () {
- startWatching(false);
- });
- }
- };
- return BaseReferenceType;
- }(SimpleType));
- /**
- * @internal
- * @hidden
- */
- var IdentifierReferenceType = /** @class */ (function (_super) {
- __extends(IdentifierReferenceType, _super);
- function IdentifierReferenceType(targetType, onInvalidated) {
- return _super.call(this, targetType, onInvalidated) || this;
- }
- IdentifierReferenceType.prototype.getValue = function (storedRefNode) {
- if (!storedRefNode.isAlive)
- return undefined;
- var storedRef = storedRefNode.storedValue;
- return storedRef.resolvedValue;
- };
- IdentifierReferenceType.prototype.getSnapshot = function (storedRefNode) {
- var ref = storedRefNode.storedValue;
- return ref.identifier;
- };
- IdentifierReferenceType.prototype.instantiate = function (parent, subpath, environment, initialValue) {
- var identifier = isStateTreeNode(initialValue)
- ? getIdentifier(initialValue)
- : initialValue;
- var storedRef = new StoredReference(initialValue, this.targetType);
- var storedRefNode = createScalarNode(this, parent, subpath, environment, storedRef);
- storedRef.node = storedRefNode;
- this.watchTargetNodeForInvalidations(storedRefNode, identifier, undefined);
- return storedRefNode;
- };
- IdentifierReferenceType.prototype.reconcile = function (current, newValue, parent, subpath) {
- if (!current.isDetaching && current.type === this) {
- var compareByValue = isStateTreeNode(newValue);
- var ref = current.storedValue;
- if ((!compareByValue && ref.identifier === newValue) ||
- (compareByValue && ref.resolvedValue === newValue)) {
- current.setParent(parent, subpath);
- return current;
- }
- }
- var newNode = this.instantiate(parent, subpath, undefined, newValue);
- current.die(); // noop if detaching
- return newNode;
- };
- return IdentifierReferenceType;
- }(BaseReferenceType));
- /**
- * @internal
- * @hidden
- */
- var CustomReferenceType = /** @class */ (function (_super) {
- __extends(CustomReferenceType, _super);
- function CustomReferenceType(targetType, options, onInvalidated) {
- var _this = _super.call(this, targetType, onInvalidated) || this;
- _this.options = options;
- return _this;
- }
- CustomReferenceType.prototype.getValue = function (storedRefNode) {
- if (!storedRefNode.isAlive)
- return undefined;
- var referencedNode = this.options.get(storedRefNode.storedValue, storedRefNode.parent ? storedRefNode.parent.storedValue : null);
- return referencedNode;
- };
- CustomReferenceType.prototype.getSnapshot = function (storedRefNode) {
- return storedRefNode.storedValue;
- };
- CustomReferenceType.prototype.instantiate = function (parent, subpath, environment, newValue) {
- var identifier = isStateTreeNode(newValue)
- ? this.options.set(newValue, parent ? parent.storedValue : null)
- : newValue;
- var storedRefNode = createScalarNode(this, parent, subpath, environment, identifier);
- this.watchTargetNodeForInvalidations(storedRefNode, identifier, this.options);
- return storedRefNode;
- };
- CustomReferenceType.prototype.reconcile = function (current, newValue, parent, subpath) {
- var newIdentifier = isStateTreeNode(newValue)
- ? this.options.set(newValue, current ? current.storedValue : null)
- : newValue;
- if (!current.isDetaching &&
- current.type === this &&
- current.storedValue === newIdentifier) {
- current.setParent(parent, subpath);
- return current;
- }
- var newNode = this.instantiate(parent, subpath, undefined, newIdentifier);
- current.die(); // noop if detaching
- return newNode;
- };
- return CustomReferenceType;
- }(BaseReferenceType));
- /**
- * `types.reference` - Creates a reference to another type, which should have defined an identifier.
- * See also the [reference and identifiers](https://github.com/mobxjs/mobx-state-tree#references-and-identifiers) section.
- */
- function reference(subType, options) {
- assertIsType(subType, 1);
- if (devMode()) {
- if (arguments.length === 2 && typeof arguments[1] === "string") {
- // istanbul ignore next
- throw fail$1("References with base path are no longer supported. Please remove the base path.");
- }
- }
- var getSetOptions = options ? options : undefined;
- var onInvalidated = options
- ? options.onInvalidated
- : undefined;
- if (getSetOptions && (getSetOptions.get || getSetOptions.set)) {
- if (devMode()) {
- if (!getSetOptions.get || !getSetOptions.set) {
- throw fail$1("reference options must either contain both a 'get' and a 'set' method or none of them");
- }
- }
- return new CustomReferenceType(subType, {
- get: getSetOptions.get,
- set: getSetOptions.set
- }, onInvalidated);
- }
- else {
- return new IdentifierReferenceType(subType, onInvalidated);
- }
- }
- /**
- * Returns if a given value represents a reference type.
- *
- * @param type
- * @returns
- */
- function isReferenceType(type) {
- return (type.flags & TypeFlags.Reference) > 0;
- }
- /**
- * `types.safeReference` - A safe reference is like a standard reference, except that it accepts the undefined value by default
- * and automatically sets itself to undefined (when the parent is a model) / removes itself from arrays and maps
- * when the reference it is pointing to gets detached/destroyed.
- *
- * The optional options parameter object accepts a parameter named `acceptsUndefined`, which is set to true by default, so it is suitable
- * for model properties.
- * When used inside collections (arrays/maps), it is recommended to set this option to false so it can't take undefined as value,
- * which is usually the desired in those cases.
- *
- * Strictly speaking it is a `types.maybe(types.reference(X))` (when `acceptsUndefined` is set to true, the default) and
- * `types.reference(X)` (when `acceptsUndefined` is set to false), both of them with a customized `onInvalidated` option.
- *
- * @param subType
- * @param options
- * @returns
- */
- function safeReference(subType, options) {
- var refType = reference(subType, __assign(__assign({}, options), { onInvalidated: function (ev) {
- ev.removeRef();
- } }));
- if (options && options.acceptsUndefined === false) {
- return refType;
- }
- else {
- return maybe(refType);
- }
- }
- var BaseIdentifierType = /** @class */ (function (_super) {
- __extends(BaseIdentifierType, _super);
- function BaseIdentifierType(name, validType) {
- var _this = _super.call(this, name) || this;
- _this.validType = validType;
- _this.flags = TypeFlags.Identifier;
- return _this;
- }
- BaseIdentifierType.prototype.instantiate = function (parent, subpath, environment, initialValue) {
- if (!parent || !(parent.type instanceof ModelType))
- throw fail$1("Identifier types can only be instantiated as direct child of a model type");
- return createScalarNode(this, parent, subpath, environment, initialValue);
- };
- BaseIdentifierType.prototype.reconcile = function (current, newValue, parent, subpath) {
- // we don't consider detaching here since identifier are scalar nodes, and scalar nodes cannot be detached
- if (current.storedValue !== newValue)
- throw fail$1("Tried to change identifier from '" + current.storedValue + "' to '" + newValue + "'. Changing identifiers is not allowed.");
- current.setParent(parent, subpath);
- return current;
- };
- BaseIdentifierType.prototype.isValidSnapshot = function (value, context) {
- if (typeof value !== this.validType) {
- return typeCheckFailure(context, value, "Value is not a valid " + this.describe() + ", expected a " + this.validType);
- }
- return typeCheckSuccess();
- };
- return BaseIdentifierType;
- }(SimpleType));
- /**
- * @internal
- * @hidden
- */
- var IdentifierType = /** @class */ (function (_super) {
- __extends(IdentifierType, _super);
- function IdentifierType() {
- var _this = _super.call(this, "identifier", "string") || this;
- _this.flags = TypeFlags.Identifier;
- return _this;
- }
- IdentifierType.prototype.describe = function () {
- return "identifier";
- };
- return IdentifierType;
- }(BaseIdentifierType));
- /**
- * @internal
- * @hidden
- */
- var IdentifierNumberType = /** @class */ (function (_super) {
- __extends(IdentifierNumberType, _super);
- function IdentifierNumberType() {
- return _super.call(this, "identifierNumber", "number") || this;
- }
- IdentifierNumberType.prototype.getSnapshot = function (node) {
- return node.storedValue;
- };
- IdentifierNumberType.prototype.describe = function () {
- return "identifierNumber";
- };
- return IdentifierNumberType;
- }(BaseIdentifierType));
- /**
- * `types.identifier` - Identifiers are used to make references, lifecycle events and reconciling works.
- * Inside a state tree, for each type can exist only one instance for each given identifier.
- * For example there couldn't be 2 instances of user with id 1. If you need more, consider using references.
- * Identifier can be used only as type property of a model.
- * This type accepts as parameter the value type of the identifier field that can be either string or number.
- *
- * Example:
- * ```ts
- * const Todo = types.model("Todo", {
- * id: types.identifier,
- * title: types.string
- * })
- * ```
- *
- * @returns
- */
- var identifier = new IdentifierType();
- /**
- * `types.identifierNumber` - Similar to `types.identifier`. This one will serialize from / to a number when applying snapshots
- *
- * Example:
- * ```ts
- * const Todo = types.model("Todo", {
- * id: types.identifierNumber,
- * title: types.string
- * })
- * ```
- *
- * @returns
- */
- var identifierNumber = new IdentifierNumberType();
- /**
- * Returns if a given value represents an identifier type.
- *
- * @param type
- * @returns
- */
- function isIdentifierType(type) {
- return isType(type) && (type.flags & TypeFlags.Identifier) > 0;
- }
- /**
- * @internal
- * @hidden
- */
- function normalizeIdentifier(id) {
- return "" + id;
- }
- /**
- * @internal
- * @hidden
- */
- function isValidIdentifier(id) {
- return typeof id === "string" || typeof id === "number";
- }
- /**
- * @internal
- * @hidden
- */
- function assertIsValidIdentifier(id, argNumber) {
- assertArg(id, isValidIdentifier, "string or number (identifier)", argNumber);
- }
- /**
- * `types.custom` - Creates a custom type. Custom types can be used for arbitrary immutable values, that have a serializable representation. For example, to create your own Date representation, Decimal type etc.
- *
- * The signature of the options is:
- * ```ts
- * export interface CustomTypeOptions<S, T> {
- * // Friendly name
- * name: string
- * // given a serialized value, how to turn it into the target type
- * fromSnapshot(snapshot: S): T
- * // return the serialization of the current value
- * toSnapshot(value: T): S
- * // if true, this is a converted value, if false, it's a snapshot
- * isTargetType(value: T | S): value is T
- * // a non empty string is assumed to be a validation error
- * getValidationMessage?(snapshot: S): string
- * }
- * ```
- *
- * Example:
- * ```ts
- * const DecimalPrimitive = types.custom<string, Decimal>({
- * name: "Decimal",
- * fromSnapshot(value: string) {
- * return new Decimal(value)
- * },
- * toSnapshot(value: Decimal) {
- * return value.toString()
- * },
- * isTargetType(value: string | Decimal): boolean {
- * return value instanceof Decimal
- * },
- * getValidationMessage(value: string): string {
- * if (/^-?\d+\.\d+$/.test(value)) return "" // OK
- * return `'${value}' doesn't look like a valid decimal number`
- * }
- * })
- *
- * const Wallet = types.model({
- * balance: DecimalPrimitive
- * })
- * ```
- *
- * @param options
- * @returns
- */
- function custom(options) {
- return new CustomType(options);
- }
- /**
- * @internal
- * @hidden
- */
- var CustomType = /** @class */ (function (_super) {
- __extends(CustomType, _super);
- function CustomType(options) {
- var _this = _super.call(this, options.name) || this;
- _this.options = options;
- _this.flags = TypeFlags.Custom;
- return _this;
- }
- CustomType.prototype.describe = function () {
- return this.name;
- };
- CustomType.prototype.isValidSnapshot = function (value, context) {
- if (this.options.isTargetType(value))
- return typeCheckSuccess();
- var typeError = this.options.getValidationMessage(value);
- if (typeError) {
- return typeCheckFailure(context, value, "Invalid value for type '" + this.name + "': " + typeError);
- }
- return typeCheckSuccess();
- };
- CustomType.prototype.getSnapshot = function (node) {
- return this.options.toSnapshot(node.storedValue);
- };
- CustomType.prototype.instantiate = function (parent, subpath, environment, initialValue) {
- var valueToStore = this.options.isTargetType(initialValue)
- ? initialValue
- : this.options.fromSnapshot(initialValue);
- return createScalarNode(this, parent, subpath, environment, valueToStore);
- };
- CustomType.prototype.reconcile = function (current, value, parent, subpath) {
- var isSnapshot = !this.options.isTargetType(value);
- // in theory customs use scalar nodes which cannot be detached, but still...
- if (!current.isDetaching) {
- var unchanged = current.type === this &&
- (isSnapshot ? value === current.snapshot : value === current.storedValue);
- if (unchanged) {
- current.setParent(parent, subpath);
- return current;
- }
- }
- var valueToStore = isSnapshot ? this.options.fromSnapshot(value) : value;
- var newNode = this.instantiate(parent, subpath, undefined, valueToStore);
- current.die(); // noop if detaching
- return newNode;
- };
- return CustomType;
- }(SimpleType));
- // we import the types to re-export them inside types.
- var types = {
- enumeration: enumeration,
- model: model,
- compose: compose,
- custom: custom,
- reference: reference,
- safeReference: safeReference,
- union: union,
- optional: optional,
- literal: literal,
- maybe: maybe,
- maybeNull: maybeNull,
- refinement: refinement,
- string: string,
- boolean: boolean,
- number: number,
- integer: integer,
- Date: DatePrimitive,
- map: map,
- array: array,
- frozen: frozen,
- identifier: identifier,
- identifierNumber: identifierNumber,
- late: late,
- undefined: undefinedType,
- null: nullType,
- snapshotProcessor: snapshotProcessor
- };
- exports.addDisposer = addDisposer;
- exports.addMiddleware = addMiddleware;
- exports.applyAction = applyAction;
- exports.applyPatch = applyPatch;
- exports.applySnapshot = applySnapshot;
- exports.cast = cast;
- exports.castFlowReturn = castFlowReturn;
- exports.castToReferenceSnapshot = castToReferenceSnapshot;
- exports.castToSnapshot = castToSnapshot;
- exports.clone = clone;
- exports.createActionTrackingMiddleware = createActionTrackingMiddleware;
- exports.createActionTrackingMiddleware2 = createActionTrackingMiddleware2;
- exports.decorate = decorate;
- exports.destroy = destroy;
- exports.detach = detach;
- exports.escapeJsonPath = escapeJsonPath;
- exports.flow = flow;
- exports.getChildType = getChildType;
- exports.getEnv = getEnv;
- exports.getIdentifier = getIdentifier;
- exports.getLivelinessChecking = getLivelinessChecking;
- exports.getMembers = getMembers;
- exports.getNodeId = getNodeId;
- exports.getParent = getParent;
- exports.getParentOfType = getParentOfType;
- exports.getPath = getPath;
- exports.getPathParts = getPathParts;
- exports.getPropertyMembers = getPropertyMembers;
- exports.getRelativePath = getRelativePath;
- exports.getRoot = getRoot;
- exports.getRunningActionContext = getRunningActionContext;
- exports.getSnapshot = getSnapshot;
- exports.getType = getType;
- exports.hasParent = hasParent;
- exports.hasParentOfType = hasParentOfType;
- exports.isActionContextChildOf = isActionContextChildOf;
- exports.isActionContextThisOrChildOf = isActionContextThisOrChildOf;
- exports.isAlive = isAlive;
- exports.isArrayType = isArrayType;
- exports.isFrozenType = isFrozenType;
- exports.isIdentifierType = isIdentifierType;
- exports.isLateType = isLateType;
- exports.isLiteralType = isLiteralType;
- exports.isMapType = isMapType;
- exports.isModelType = isModelType;
- exports.isOptionalType = isOptionalType;
- exports.isPrimitiveType = isPrimitiveType;
- exports.isProtected = isProtected;
- exports.isReferenceType = isReferenceType;
- exports.isRefinementType = isRefinementType;
- exports.isRoot = isRoot;
- exports.isStateTreeNode = isStateTreeNode;
- exports.isType = isType;
- exports.isUnionType = isUnionType;
- exports.isValidReference = isValidReference;
- exports.joinJsonPath = joinJsonPath;
- exports.onAction = onAction;
- exports.onPatch = onPatch;
- exports.onSnapshot = onSnapshot;
- exports.process = process$1;
- exports.protect = protect;
- exports.recordActions = recordActions;
- exports.recordPatches = recordPatches;
- exports.resolveIdentifier = resolveIdentifier;
- exports.resolvePath = resolvePath;
- exports.setLivelinessChecking = setLivelinessChecking;
- exports.setLivelynessChecking = setLivelynessChecking;
- exports.splitJsonPath = splitJsonPath;
- exports.tryReference = tryReference;
- exports.tryResolve = tryResolve;
- exports.typecheck = typecheck;
- exports.types = types;
- exports.unescapeJsonPath = unescapeJsonPath;
- exports.unprotect = unprotect;
- exports.walk = walk;
|