mobx-state-tree.js 230 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471
  1. 'use strict';
  2. Object.defineProperty(exports, '__esModule', { value: true });
  3. var mobx = require('mobx');
  4. var livelinessChecking = "warn";
  5. /**
  6. * Defines what MST should do when running into reads / writes to objects that have died.
  7. * By default it will print a warning.
  8. * Use the `"error"` option to easy debugging to see where the error was thrown and when the offending read / write took place
  9. *
  10. * @param mode `"warn"`, `"error"` or `"ignore"`
  11. */
  12. function setLivelinessChecking(mode) {
  13. livelinessChecking = mode;
  14. }
  15. /**
  16. * Returns the current liveliness checking mode.
  17. *
  18. * @returns `"warn"`, `"error"` or `"ignore"`
  19. */
  20. function getLivelinessChecking() {
  21. return livelinessChecking;
  22. }
  23. /**
  24. * @deprecated use setLivelinessChecking instead
  25. * @hidden
  26. *
  27. * Defines what MST should do when running into reads / writes to objects that have died.
  28. * By default it will print a warning.
  29. * Use the `"error"` option to easy debugging to see where the error was thrown and when the offending read / write took place
  30. *
  31. * @param mode `"warn"`, `"error"` or `"ignore"`
  32. */
  33. function setLivelynessChecking(mode) {
  34. setLivelinessChecking(mode);
  35. }
  36. /**
  37. * @hidden
  38. */
  39. var Hook;
  40. (function (Hook) {
  41. Hook["afterCreate"] = "afterCreate";
  42. Hook["afterAttach"] = "afterAttach";
  43. Hook["afterCreationFinalization"] = "afterCreationFinalization";
  44. Hook["beforeDetach"] = "beforeDetach";
  45. Hook["beforeDestroy"] = "beforeDestroy";
  46. })(Hook || (Hook = {}));
  47. /*! *****************************************************************************
  48. Copyright (c) Microsoft Corporation. All rights reserved.
  49. Licensed under the Apache License, Version 2.0 (the "License"); you may not use
  50. this file except in compliance with the License. You may obtain a copy of the
  51. License at http://www.apache.org/licenses/LICENSE-2.0
  52. THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  53. KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
  54. WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
  55. MERCHANTABLITY OR NON-INFRINGEMENT.
  56. See the Apache Version 2.0 License for specific language governing permissions
  57. and limitations under the License.
  58. ***************************************************************************** */
  59. /* global Reflect, Promise */
  60. var extendStatics = function(d, b) {
  61. extendStatics = Object.setPrototypeOf ||
  62. ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
  63. function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
  64. return extendStatics(d, b);
  65. };
  66. function __extends(d, b) {
  67. extendStatics(d, b);
  68. function __() { this.constructor = d; }
  69. d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  70. }
  71. var __assign = function() {
  72. __assign = Object.assign || function __assign(t) {
  73. for (var s, i = 1, n = arguments.length; i < n; i++) {
  74. s = arguments[i];
  75. for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
  76. }
  77. return t;
  78. };
  79. return __assign.apply(this, arguments);
  80. };
  81. function __rest(s, e) {
  82. var t = {};
  83. for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
  84. t[p] = s[p];
  85. if (s != null && typeof Object.getOwnPropertySymbols === "function")
  86. for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
  87. if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
  88. t[p[i]] = s[p[i]];
  89. }
  90. return t;
  91. }
  92. function __decorate(decorators, target, key, desc) {
  93. var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
  94. if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
  95. 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;
  96. return c > 3 && r && Object.defineProperty(target, key, r), r;
  97. }
  98. function __values(o) {
  99. var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0;
  100. if (m) return m.call(o);
  101. return {
  102. next: function () {
  103. if (o && i >= o.length) o = void 0;
  104. return { value: o && o[i++], done: !o };
  105. }
  106. };
  107. }
  108. function __read(o, n) {
  109. var m = typeof Symbol === "function" && o[Symbol.iterator];
  110. if (!m) return o;
  111. var i = m.call(o), r, ar = [], e;
  112. try {
  113. while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
  114. }
  115. catch (error) { e = { error: error }; }
  116. finally {
  117. try {
  118. if (r && !r.done && (m = i["return"])) m.call(i);
  119. }
  120. finally { if (e) throw e.error; }
  121. }
  122. return ar;
  123. }
  124. function __spread() {
  125. for (var ar = [], i = 0; i < arguments.length; i++)
  126. ar = ar.concat(__read(arguments[i]));
  127. return ar;
  128. }
  129. /**
  130. * Returns the _actual_ type of the given tree node. (Or throws)
  131. *
  132. * @param object
  133. * @returns
  134. */
  135. function getType(object) {
  136. assertIsStateTreeNode(object, 1);
  137. return getStateTreeNode(object).type;
  138. }
  139. /**
  140. * Returns the _declared_ type of the given sub property of an object, array or map.
  141. * In the case of arrays and maps the property name is optional and will be ignored.
  142. *
  143. * Example:
  144. * ```ts
  145. * const Box = types.model({ x: 0, y: 0 })
  146. * const box = Box.create()
  147. *
  148. * console.log(getChildType(box, "x").name) // 'number'
  149. * ```
  150. *
  151. * @param object
  152. * @param propertyName
  153. * @returns
  154. */
  155. function getChildType(object, propertyName) {
  156. assertIsStateTreeNode(object, 1);
  157. return getStateTreeNode(object).getChildType(propertyName);
  158. }
  159. /**
  160. * Registers a function that will be invoked for each mutation that is applied to the provided model instance, or to any of its children.
  161. * 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.
  162. * Patches can be used to deep observe a model tree.
  163. *
  164. * @param target the model instance from which to receive patches
  165. * @param callback the callback that is invoked for each patch. The reversePatch is a patch that would actually undo the emitted patch
  166. * @returns function to remove the listener
  167. */
  168. function onPatch(target, callback) {
  169. // check all arguments
  170. assertIsStateTreeNode(target, 1);
  171. assertIsFunction(callback, 2);
  172. return getStateTreeNode(target).onPatch(callback);
  173. }
  174. /**
  175. * Registers a function that is invoked whenever a new snapshot for the given model instance is available.
  176. * The listener will only be fire at the end of the current MobX (trans)action.
  177. * See [snapshots](https://github.com/mobxjs/mobx-state-tree#snapshots) for more details.
  178. *
  179. * @param target
  180. * @param callback
  181. * @returns
  182. */
  183. function onSnapshot(target, callback) {
  184. // check all arguments
  185. assertIsStateTreeNode(target, 1);
  186. assertIsFunction(callback, 2);
  187. return getStateTreeNode(target).onSnapshot(callback);
  188. }
  189. /**
  190. * Applies a JSON-patch to the given model instance or bails out if the patch couldn't be applied
  191. * See [patches](https://github.com/mobxjs/mobx-state-tree#patches) for more details.
  192. *
  193. * Can apply a single past, or an array of patches.
  194. *
  195. * @param target
  196. * @param patch
  197. * @returns
  198. */
  199. function applyPatch(target, patch) {
  200. // check all arguments
  201. assertIsStateTreeNode(target, 1);
  202. assertArg(patch, function (p) { return typeof p === "object"; }, "object or array", 2);
  203. getStateTreeNode(target).applyPatches(asArray(patch));
  204. }
  205. /**
  206. * Small abstraction around `onPatch` and `applyPatch`, attaches a patch listener to a tree and records all the patches.
  207. * Returns an recorder object with the following signature:
  208. *
  209. * Example:
  210. * ```ts
  211. * export interface IPatchRecorder {
  212. * // the recorded patches
  213. * patches: IJsonPatch[]
  214. * // the inverse of the recorded patches
  215. * inversePatches: IJsonPatch[]
  216. * // true if currently recording
  217. * recording: boolean
  218. * // stop recording patches
  219. * stop(): void
  220. * // resume recording patches
  221. * resume(): void
  222. * // apply all the recorded patches on the given target (the original subject if omitted)
  223. * replay(target?: IAnyStateTreeNode): void
  224. * // reverse apply the recorded patches on the given target (the original subject if omitted)
  225. * // stops the recorder if not already stopped
  226. * undo(): void
  227. * }
  228. * ```
  229. *
  230. * The optional filter function allows to skip recording certain patches.
  231. *
  232. * @param subject
  233. * @param filter
  234. * @returns
  235. */
  236. function recordPatches(subject, filter) {
  237. // check all arguments
  238. assertIsStateTreeNode(subject, 1);
  239. var data = {
  240. patches: [],
  241. reversedInversePatches: []
  242. };
  243. // we will generate the immutable copy of patches on demand for public consumption
  244. var publicData = {};
  245. var disposer;
  246. var recorder = {
  247. get recording() {
  248. return !!disposer;
  249. },
  250. get patches() {
  251. if (!publicData.patches) {
  252. publicData.patches = data.patches.slice();
  253. }
  254. return publicData.patches;
  255. },
  256. get reversedInversePatches() {
  257. if (!publicData.reversedInversePatches) {
  258. publicData.reversedInversePatches = data.reversedInversePatches.slice();
  259. }
  260. return publicData.reversedInversePatches;
  261. },
  262. get inversePatches() {
  263. if (!publicData.inversePatches) {
  264. publicData.inversePatches = data.reversedInversePatches.slice().reverse();
  265. }
  266. return publicData.inversePatches;
  267. },
  268. stop: function () {
  269. if (disposer) {
  270. disposer();
  271. disposer = undefined;
  272. }
  273. },
  274. resume: function () {
  275. if (disposer)
  276. return;
  277. disposer = onPatch(subject, function (patch, inversePatch) {
  278. // skip patches that are asked to be filtered if there's a filter in place
  279. if (filter && !filter(patch, inversePatch, getRunningActionContext())) {
  280. return;
  281. }
  282. data.patches.push(patch);
  283. data.reversedInversePatches.unshift(inversePatch);
  284. // mark immutable public patches as dirty
  285. publicData.patches = undefined;
  286. publicData.inversePatches = undefined;
  287. publicData.reversedInversePatches = undefined;
  288. });
  289. },
  290. replay: function (target) {
  291. applyPatch(target || subject, data.patches);
  292. },
  293. undo: function (target) {
  294. applyPatch(target || subject, data.reversedInversePatches);
  295. }
  296. };
  297. recorder.resume();
  298. return recorder;
  299. }
  300. /**
  301. * The inverse of `unprotect`.
  302. *
  303. * @param target
  304. */
  305. function protect(target) {
  306. // check all arguments
  307. assertIsStateTreeNode(target, 1);
  308. var node = getStateTreeNode(target);
  309. if (!node.isRoot)
  310. throw fail$1("`protect` can only be invoked on root nodes");
  311. node.isProtectionEnabled = true;
  312. }
  313. /**
  314. * By default it is not allowed to directly modify a model. Models can only be modified through actions.
  315. * However, in some cases you don't care about the advantages (like replayability, traceability, etc) this yields.
  316. * For example because you are building a PoC or don't have any middleware attached to your tree.
  317. *
  318. * In that case you can disable this protection by calling `unprotect` on the root of your tree.
  319. *
  320. * Example:
  321. * ```ts
  322. * const Todo = types.model({
  323. * done: false
  324. * }).actions(self => ({
  325. * toggle() {
  326. * self.done = !self.done
  327. * }
  328. * }))
  329. *
  330. * const todo = Todo.create()
  331. * todo.done = true // throws!
  332. * todo.toggle() // OK
  333. * unprotect(todo)
  334. * todo.done = false // OK
  335. * ```
  336. */
  337. function unprotect(target) {
  338. // check all arguments
  339. assertIsStateTreeNode(target, 1);
  340. var node = getStateTreeNode(target);
  341. if (!node.isRoot)
  342. throw fail$1("`unprotect` can only be invoked on root nodes");
  343. node.isProtectionEnabled = false;
  344. }
  345. /**
  346. * Returns true if the object is in protected mode, @see protect
  347. */
  348. function isProtected(target) {
  349. return getStateTreeNode(target).isProtected;
  350. }
  351. /**
  352. * Applies a snapshot to a given model instances. Patch and snapshot listeners will be invoked as usual.
  353. *
  354. * @param target
  355. * @param snapshot
  356. * @returns
  357. */
  358. function applySnapshot(target, snapshot) {
  359. // check all arguments
  360. assertIsStateTreeNode(target, 1);
  361. return getStateTreeNode(target).applySnapshot(snapshot);
  362. }
  363. /**
  364. * Calculates a snapshot from the given model instance. The snapshot will always reflect the latest state but use
  365. * structural sharing where possible. Doesn't require MobX transactions to be completed.
  366. *
  367. * @param target
  368. * @param applyPostProcess If true (the default) then postProcessSnapshot gets applied.
  369. * @returns
  370. */
  371. function getSnapshot(target, applyPostProcess) {
  372. if (applyPostProcess === void 0) { applyPostProcess = true; }
  373. // check all arguments
  374. assertIsStateTreeNode(target, 1);
  375. var node = getStateTreeNode(target);
  376. if (applyPostProcess)
  377. return node.snapshot;
  378. return freeze(node.type.getSnapshot(node, false));
  379. }
  380. /**
  381. * Given a model instance, returns `true` if the object has a parent, that is, is part of another object, map or array.
  382. *
  383. * @param target
  384. * @param depth How far should we look upward? 1 by default.
  385. * @returns
  386. */
  387. function hasParent(target, depth) {
  388. if (depth === void 0) { depth = 1; }
  389. // check all arguments
  390. assertIsStateTreeNode(target, 1);
  391. assertIsNumber(depth, 2, 0);
  392. var parent = getStateTreeNode(target).parent;
  393. while (parent) {
  394. if (--depth === 0)
  395. return true;
  396. parent = parent.parent;
  397. }
  398. return false;
  399. }
  400. /**
  401. * Returns the immediate parent of this object, or throws.
  402. *
  403. * Note that the immediate parent can be either an object, map or array, and
  404. * doesn't necessarily refer to the parent model.
  405. *
  406. * Please note that in child nodes access to the root is only possible
  407. * once the `afterAttach` hook has fired.
  408. *
  409. * @param target
  410. * @param depth How far should we look upward? 1 by default.
  411. * @returns
  412. */
  413. function getParent(target, depth) {
  414. if (depth === void 0) { depth = 1; }
  415. // check all arguments
  416. assertIsStateTreeNode(target, 1);
  417. assertIsNumber(depth, 2, 0);
  418. var d = depth;
  419. var parent = getStateTreeNode(target).parent;
  420. while (parent) {
  421. if (--d === 0)
  422. return parent.storedValue;
  423. parent = parent.parent;
  424. }
  425. throw fail$1("Failed to find the parent of " + getStateTreeNode(target) + " at depth " + depth);
  426. }
  427. /**
  428. * 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
  429. *
  430. * @param target
  431. * @param type
  432. * @returns
  433. */
  434. function hasParentOfType(target, type) {
  435. // check all arguments
  436. assertIsStateTreeNode(target, 1);
  437. assertIsType(type, 2);
  438. var parent = getStateTreeNode(target).parent;
  439. while (parent) {
  440. if (type.is(parent.storedValue))
  441. return true;
  442. parent = parent.parent;
  443. }
  444. return false;
  445. }
  446. /**
  447. * Returns the target's parent of a given type, or throws.
  448. *
  449. * @param target
  450. * @param type
  451. * @returns
  452. */
  453. function getParentOfType(target, type) {
  454. // check all arguments
  455. assertIsStateTreeNode(target, 1);
  456. assertIsType(type, 2);
  457. var parent = getStateTreeNode(target).parent;
  458. while (parent) {
  459. if (type.is(parent.storedValue))
  460. return parent.storedValue;
  461. parent = parent.parent;
  462. }
  463. throw fail$1("Failed to find the parent of " + getStateTreeNode(target) + " of a given type");
  464. }
  465. /**
  466. * Given an object in a model tree, returns the root object of that tree.
  467. *
  468. * Please note that in child nodes access to the root is only possible
  469. * once the `afterAttach` hook has fired.
  470. *
  471. * @param target
  472. * @returns
  473. */
  474. function getRoot(target) {
  475. // check all arguments
  476. assertIsStateTreeNode(target, 1);
  477. return getStateTreeNode(target).root.storedValue;
  478. }
  479. /**
  480. * Returns the path of the given object in the model tree
  481. *
  482. * @param target
  483. * @returns
  484. */
  485. function getPath(target) {
  486. // check all arguments
  487. assertIsStateTreeNode(target, 1);
  488. return getStateTreeNode(target).path;
  489. }
  490. /**
  491. * Returns the path of the given object as unescaped string array.
  492. *
  493. * @param target
  494. * @returns
  495. */
  496. function getPathParts(target) {
  497. // check all arguments
  498. assertIsStateTreeNode(target, 1);
  499. return splitJsonPath(getStateTreeNode(target).path);
  500. }
  501. /**
  502. * Returns true if the given object is the root of a model tree.
  503. *
  504. * @param target
  505. * @returns
  506. */
  507. function isRoot(target) {
  508. // check all arguments
  509. assertIsStateTreeNode(target, 1);
  510. return getStateTreeNode(target).isRoot;
  511. }
  512. /**
  513. * Resolves a path relatively to a given object.
  514. * Returns undefined if no value can be found.
  515. *
  516. * @param target
  517. * @param path escaped json path
  518. * @returns
  519. */
  520. function resolvePath(target, path) {
  521. // check all arguments
  522. assertIsStateTreeNode(target, 1);
  523. assertIsString(path, 2);
  524. var node = resolveNodeByPath(getStateTreeNode(target), path);
  525. return node ? node.value : undefined;
  526. }
  527. /**
  528. * Resolves a model instance given a root target, the type and the identifier you are searching for.
  529. * Returns undefined if no value can be found.
  530. *
  531. * @param type
  532. * @param target
  533. * @param identifier
  534. * @returns
  535. */
  536. function resolveIdentifier(type, target, identifier) {
  537. // check all arguments
  538. assertIsType(type, 1);
  539. assertIsStateTreeNode(target, 2);
  540. assertIsValidIdentifier(identifier, 3);
  541. var node = getStateTreeNode(target).root.identifierCache.resolve(type, normalizeIdentifier(identifier));
  542. return node ? node.value : undefined;
  543. }
  544. /**
  545. * Returns the identifier of the target node.
  546. * This is the *string normalized* identifier, which might not match the type of the identifier attribute
  547. *
  548. * @param target
  549. * @returns
  550. */
  551. function getIdentifier(target) {
  552. // check all arguments
  553. assertIsStateTreeNode(target, 1);
  554. return getStateTreeNode(target).identifier;
  555. }
  556. /**
  557. * Tests if a reference is valid (pointing to an existing node and optionally if alive) and returns such reference if it the check passes,
  558. * else it returns undefined.
  559. *
  560. * @param getter Function to access the reference.
  561. * @param checkIfAlive true to also make sure the referenced node is alive (default), false to skip this check.
  562. * @returns
  563. */
  564. function tryReference(getter, checkIfAlive) {
  565. if (checkIfAlive === void 0) { checkIfAlive = true; }
  566. try {
  567. var node = getter();
  568. if (node === undefined || node === null) {
  569. return undefined;
  570. }
  571. else if (isStateTreeNode(node)) {
  572. if (!checkIfAlive) {
  573. return node;
  574. }
  575. else {
  576. return isAlive(node) ? node : undefined;
  577. }
  578. }
  579. else {
  580. throw fail$1("The reference to be checked is not one of node, null or undefined");
  581. }
  582. }
  583. catch (e) {
  584. if (e instanceof InvalidReferenceError) {
  585. return undefined;
  586. }
  587. throw e;
  588. }
  589. }
  590. /**
  591. * Tests if a reference is valid (pointing to an existing node and optionally if alive) and returns if the check passes or not.
  592. *
  593. * @param getter Function to access the reference.
  594. * @param checkIfAlive true to also make sure the referenced node is alive (default), false to skip this check.
  595. * @returns
  596. */
  597. function isValidReference(getter, checkIfAlive) {
  598. if (checkIfAlive === void 0) { checkIfAlive = true; }
  599. try {
  600. var node = getter();
  601. if (node === undefined || node === null) {
  602. return false;
  603. }
  604. else if (isStateTreeNode(node)) {
  605. return checkIfAlive ? isAlive(node) : true;
  606. }
  607. else {
  608. throw fail$1("The reference to be checked is not one of node, null or undefined");
  609. }
  610. }
  611. catch (e) {
  612. if (e instanceof InvalidReferenceError) {
  613. return false;
  614. }
  615. throw e;
  616. }
  617. }
  618. /**
  619. * Try to resolve a given path relative to a given node.
  620. *
  621. * @param target
  622. * @param path
  623. * @returns
  624. */
  625. function tryResolve(target, path) {
  626. // check all arguments
  627. assertIsStateTreeNode(target, 1);
  628. assertIsString(path, 2);
  629. var node = resolveNodeByPath(getStateTreeNode(target), path, false);
  630. if (node === undefined)
  631. return undefined;
  632. try {
  633. return node.value;
  634. }
  635. catch (e) {
  636. // For what ever reason not resolvable (e.g. totally not existing path, or value that cannot be fetched)
  637. // see test / issue: 'try resolve doesn't work #686'
  638. return undefined;
  639. }
  640. }
  641. /**
  642. * Given two state tree nodes that are part of the same tree,
  643. * returns the shortest jsonpath needed to navigate from the one to the other
  644. *
  645. * @param base
  646. * @param target
  647. * @returns
  648. */
  649. function getRelativePath(base, target) {
  650. // check all arguments
  651. assertIsStateTreeNode(base, 1);
  652. assertIsStateTreeNode(target, 2);
  653. return getRelativePathBetweenNodes(getStateTreeNode(base), getStateTreeNode(target));
  654. }
  655. /**
  656. * Returns a deep copy of the given state tree node as new tree.
  657. * Short hand for `snapshot(x) = getType(x).create(getSnapshot(x))`
  658. *
  659. * _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_
  660. *
  661. * @param source
  662. * @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.
  663. * @returns
  664. */
  665. function clone(source, keepEnvironment) {
  666. if (keepEnvironment === void 0) { keepEnvironment = true; }
  667. // check all arguments
  668. assertIsStateTreeNode(source, 1);
  669. var node = getStateTreeNode(source);
  670. return node.type.create(node.snapshot, keepEnvironment === true
  671. ? node.root.environment
  672. : keepEnvironment === false
  673. ? undefined
  674. : keepEnvironment); // it's an object or something else
  675. }
  676. /**
  677. * Removes a model element from the state tree, and let it live on as a new state tree
  678. */
  679. function detach(target) {
  680. // check all arguments
  681. assertIsStateTreeNode(target, 1);
  682. getStateTreeNode(target).detach();
  683. return target;
  684. }
  685. /**
  686. * Removes a model element from the state tree, and mark it as end-of-life; the element should not be used anymore
  687. */
  688. function destroy(target) {
  689. // check all arguments
  690. assertIsStateTreeNode(target, 1);
  691. var node = getStateTreeNode(target);
  692. if (node.isRoot)
  693. node.die();
  694. else
  695. node.parent.removeChild(node.subpath);
  696. }
  697. /**
  698. * Returns true if the given state tree node is not killed yet.
  699. * This means that the node is still a part of a tree, and that `destroy`
  700. * has not been called. If a node is not alive anymore, the only thing one can do with it
  701. * is requesting it's last path and snapshot
  702. *
  703. * @param target
  704. * @returns
  705. */
  706. function isAlive(target) {
  707. // check all arguments
  708. assertIsStateTreeNode(target, 1);
  709. return getStateTreeNode(target).observableIsAlive;
  710. }
  711. /**
  712. * Use this utility to register a function that should be called whenever the
  713. * targeted state tree node is destroyed. This is a useful alternative to managing
  714. * cleanup methods yourself using the `beforeDestroy` hook.
  715. *
  716. * This methods returns the same disposer that was passed as argument.
  717. *
  718. * Example:
  719. * ```ts
  720. * const Todo = types.model({
  721. * title: types.string
  722. * }).actions(self => ({
  723. * afterCreate() {
  724. * const autoSaveDisposer = reaction(
  725. * () => getSnapshot(self),
  726. * snapshot => sendSnapshotToServerSomehow(snapshot)
  727. * )
  728. * // stop sending updates to server if this
  729. * // instance is destroyed
  730. * addDisposer(self, autoSaveDisposer)
  731. * }
  732. * }))
  733. * ```
  734. *
  735. * @param target
  736. * @param disposer
  737. * @returns The same disposer that was passed as argument
  738. */
  739. function addDisposer(target, disposer) {
  740. // check all arguments
  741. assertIsStateTreeNode(target, 1);
  742. assertIsFunction(disposer, 2);
  743. var node = getStateTreeNode(target);
  744. node.addDisposer(disposer);
  745. return disposer;
  746. }
  747. /**
  748. * Returns the environment of the current state tree. For more info on environments,
  749. * see [Dependency injection](https://github.com/mobxjs/mobx-state-tree#dependency-injection)
  750. *
  751. * Please note that in child nodes access to the root is only possible
  752. * once the `afterAttach` hook has fired
  753. *
  754. * Returns an empty environment if the tree wasn't initialized with an environment
  755. *
  756. * @param target
  757. * @returns
  758. */
  759. function getEnv(target) {
  760. // check all arguments
  761. assertIsStateTreeNode(target, 1);
  762. var node = getStateTreeNode(target);
  763. var env = node.root.environment;
  764. if (!env)
  765. return EMPTY_OBJECT;
  766. return env;
  767. }
  768. /**
  769. * Performs a depth first walk through a tree.
  770. */
  771. function walk(target, processor) {
  772. // check all arguments
  773. assertIsStateTreeNode(target, 1);
  774. assertIsFunction(processor, 2);
  775. var node = getStateTreeNode(target);
  776. // tslint:disable-next-line:no_unused-variable
  777. node.getChildren().forEach(function (child) {
  778. if (isStateTreeNode(child.storedValue))
  779. walk(child.storedValue, processor);
  780. });
  781. processor(node.storedValue);
  782. }
  783. /**
  784. * Returns a reflection of the model type properties and name for either a model type or model node.
  785. *
  786. * @param typeOrNode
  787. * @returns
  788. */
  789. function getPropertyMembers(typeOrNode) {
  790. var type;
  791. if (isStateTreeNode(typeOrNode)) {
  792. type = getType(typeOrNode);
  793. }
  794. else {
  795. type = typeOrNode;
  796. }
  797. assertArg(type, function (t) { return isModelType(t); }, "model type or model instance", 1);
  798. return {
  799. name: type.name,
  800. properties: __assign({}, type.properties)
  801. };
  802. }
  803. /**
  804. * Returns a reflection of the model node, including name, properties, views, volatile and actions.
  805. *
  806. * @param target
  807. * @returns
  808. */
  809. function getMembers(target) {
  810. var type = getStateTreeNode(target).type;
  811. var reflected = __assign(__assign({}, getPropertyMembers(type)), { actions: [], volatile: [], views: [] });
  812. var props = Object.getOwnPropertyNames(target);
  813. props.forEach(function (key) {
  814. if (key in reflected.properties)
  815. return;
  816. var descriptor = Object.getOwnPropertyDescriptor(target, key);
  817. if (descriptor.get) {
  818. if (mobx.isComputedProp(target, key))
  819. reflected.views.push(key);
  820. else
  821. reflected.volatile.push(key);
  822. return;
  823. }
  824. if (descriptor.value._isMSTAction === true)
  825. reflected.actions.push(key);
  826. else if (mobx.isObservableProp(target, key))
  827. reflected.volatile.push(key);
  828. else
  829. reflected.views.push(key);
  830. });
  831. return reflected;
  832. }
  833. /**
  834. * Casts a node snapshot or instance type to an instance type so it can be assigned to a type instance.
  835. * Note that this is just a cast for the type system, this is, it won't actually convert a snapshot to an instance,
  836. * but just fool typescript into thinking so.
  837. * Either way, casting when outside an assignation operation won't compile.
  838. *
  839. * Example:
  840. * ```ts
  841. * const ModelA = types.model({
  842. * n: types.number
  843. * }).actions(self => ({
  844. * setN(aNumber: number) {
  845. * self.n = aNumber
  846. * }
  847. * }))
  848. *
  849. * const ModelB = types.model({
  850. * innerModel: ModelA
  851. * }).actions(self => ({
  852. * someAction() {
  853. * // this will allow the compiler to assign a snapshot to the property
  854. * self.innerModel = cast({ a: 5 })
  855. * }
  856. * }))
  857. * ```
  858. *
  859. * @param snapshotOrInstance Snapshot or instance
  860. * @returns The same object casted as an instance
  861. */
  862. function cast(snapshotOrInstance) {
  863. return snapshotOrInstance;
  864. }
  865. /**
  866. * 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).
  867. * Note that this is just a cast for the type system, this is, it won't actually convert an instance to a snapshot,
  868. * but just fool typescript into thinking so.
  869. *
  870. * Example:
  871. * ```ts
  872. * const ModelA = types.model({
  873. * n: types.number
  874. * }).actions(self => ({
  875. * setN(aNumber: number) {
  876. * self.n = aNumber
  877. * }
  878. * }))
  879. *
  880. * const ModelB = types.model({
  881. * innerModel: ModelA
  882. * })
  883. *
  884. * const a = ModelA.create({ n: 5 });
  885. * // this will allow the compiler to use a model as if it were a snapshot
  886. * const b = ModelB.create({ innerModel: castToSnapshot(a)})
  887. * ```
  888. *
  889. * @param snapshotOrInstance Snapshot or instance
  890. * @returns The same object casted as an input (creation) snapshot
  891. */
  892. function castToSnapshot(snapshotOrInstance) {
  893. return snapshotOrInstance;
  894. }
  895. /**
  896. * 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).
  897. * Note that this is just a cast for the type system, this is, it won't actually convert an instance to a refererence snapshot,
  898. * but just fool typescript into thinking so.
  899. *
  900. * Example:
  901. * ```ts
  902. * const ModelA = types.model({
  903. * id: types.identifier,
  904. * n: types.number
  905. * }).actions(self => ({
  906. * setN(aNumber: number) {
  907. * self.n = aNumber
  908. * }
  909. * }))
  910. *
  911. * const ModelB = types.model({
  912. * refA: types.reference(ModelA)
  913. * })
  914. *
  915. * const a = ModelA.create({ id: 'someId', n: 5 });
  916. * // this will allow the compiler to use a model as if it were a reference snapshot
  917. * const b = ModelB.create({ refA: castToReference(a)})
  918. * ```
  919. *
  920. * @param instance Instance
  921. * @returns The same object casted as an reference snapshot (string or number)
  922. */
  923. function castToReferenceSnapshot(instance) {
  924. return instance;
  925. }
  926. /**
  927. * Returns the unique node id (not to be confused with the instance identifier) for a
  928. * given instance.
  929. * This id is a number that is unique for each instance.
  930. *
  931. * @export
  932. * @param target
  933. * @returns
  934. */
  935. function getNodeId(target) {
  936. assertIsStateTreeNode(target, 1);
  937. return getStateTreeNode(target).nodeId;
  938. }
  939. /**
  940. * @internal
  941. * @hidden
  942. */
  943. var BaseNode = /** @class */ (function () {
  944. function BaseNode(type, parent, subpath, environment) {
  945. this.type = type;
  946. this.environment = environment;
  947. this._state = NodeLifeCycle.INITIALIZING;
  948. this.environment = environment;
  949. this.baseSetParent(parent, subpath);
  950. }
  951. Object.defineProperty(BaseNode.prototype, "subpath", {
  952. get: function () {
  953. return this._subpath;
  954. },
  955. enumerable: true,
  956. configurable: true
  957. });
  958. Object.defineProperty(BaseNode.prototype, "subpathUponDeath", {
  959. get: function () {
  960. return this._subpathUponDeath;
  961. },
  962. enumerable: true,
  963. configurable: true
  964. });
  965. Object.defineProperty(BaseNode.prototype, "pathUponDeath", {
  966. get: function () {
  967. return this._pathUponDeath;
  968. },
  969. enumerable: true,
  970. configurable: true
  971. });
  972. Object.defineProperty(BaseNode.prototype, "value", {
  973. get: function () {
  974. return this.type.getValue(this);
  975. },
  976. enumerable: true,
  977. configurable: true
  978. });
  979. Object.defineProperty(BaseNode.prototype, "state", {
  980. get: function () {
  981. return this._state;
  982. },
  983. set: function (val) {
  984. var wasAlive = this.isAlive;
  985. this._state = val;
  986. var isAlive = this.isAlive;
  987. if (this.aliveAtom && wasAlive !== isAlive) {
  988. this.aliveAtom.reportChanged();
  989. }
  990. },
  991. enumerable: true,
  992. configurable: true
  993. });
  994. BaseNode.prototype.fireInternalHook = function (name) {
  995. if (this._hookSubscribers) {
  996. this._hookSubscribers.emit(name, this, name);
  997. }
  998. };
  999. BaseNode.prototype.registerHook = function (hook, hookHandler) {
  1000. if (!this._hookSubscribers) {
  1001. this._hookSubscribers = new EventHandlers();
  1002. }
  1003. return this._hookSubscribers.register(hook, hookHandler);
  1004. };
  1005. Object.defineProperty(BaseNode.prototype, "parent", {
  1006. get: function () {
  1007. return this._parent;
  1008. },
  1009. enumerable: true,
  1010. configurable: true
  1011. });
  1012. BaseNode.prototype.baseSetParent = function (parent, subpath) {
  1013. this._parent = parent;
  1014. this._subpath = subpath;
  1015. this._escapedSubpath = undefined; // regenerate when needed
  1016. if (this.pathAtom) {
  1017. this.pathAtom.reportChanged();
  1018. }
  1019. };
  1020. Object.defineProperty(BaseNode.prototype, "path", {
  1021. /*
  1022. * Returns (escaped) path representation as string
  1023. */
  1024. get: function () {
  1025. return this.getEscapedPath(true);
  1026. },
  1027. enumerable: true,
  1028. configurable: true
  1029. });
  1030. BaseNode.prototype.getEscapedPath = function (reportObserved) {
  1031. if (reportObserved) {
  1032. if (!this.pathAtom) {
  1033. this.pathAtom = mobx.createAtom("path");
  1034. }
  1035. this.pathAtom.reportObserved();
  1036. }
  1037. if (!this.parent)
  1038. return "";
  1039. // regenerate escaped subpath if needed
  1040. if (this._escapedSubpath === undefined) {
  1041. this._escapedSubpath = !this._subpath ? "" : escapeJsonPath(this._subpath);
  1042. }
  1043. return this.parent.getEscapedPath(reportObserved) + "/" + this._escapedSubpath;
  1044. };
  1045. Object.defineProperty(BaseNode.prototype, "isRoot", {
  1046. get: function () {
  1047. return this.parent === null;
  1048. },
  1049. enumerable: true,
  1050. configurable: true
  1051. });
  1052. Object.defineProperty(BaseNode.prototype, "isAlive", {
  1053. get: function () {
  1054. return this.state !== NodeLifeCycle.DEAD;
  1055. },
  1056. enumerable: true,
  1057. configurable: true
  1058. });
  1059. Object.defineProperty(BaseNode.prototype, "isDetaching", {
  1060. get: function () {
  1061. return this.state === NodeLifeCycle.DETACHING;
  1062. },
  1063. enumerable: true,
  1064. configurable: true
  1065. });
  1066. Object.defineProperty(BaseNode.prototype, "observableIsAlive", {
  1067. get: function () {
  1068. if (!this.aliveAtom) {
  1069. this.aliveAtom = mobx.createAtom("alive");
  1070. }
  1071. this.aliveAtom.reportObserved();
  1072. return this.isAlive;
  1073. },
  1074. enumerable: true,
  1075. configurable: true
  1076. });
  1077. BaseNode.prototype.baseFinalizeCreation = function (whenFinalized) {
  1078. if (devMode()) {
  1079. if (!this.isAlive) {
  1080. // istanbul ignore next
  1081. throw fail("assertion failed: cannot finalize the creation of a node that is already dead");
  1082. }
  1083. }
  1084. // goal: afterCreate hooks runs depth-first. After attach runs parent first, so on afterAttach the parent has completed already
  1085. if (this.state === NodeLifeCycle.CREATED) {
  1086. if (this.parent) {
  1087. if (this.parent.state !== NodeLifeCycle.FINALIZED) {
  1088. // parent not ready yet, postpone
  1089. return;
  1090. }
  1091. this.fireHook(Hook.afterAttach);
  1092. }
  1093. this.state = NodeLifeCycle.FINALIZED;
  1094. if (whenFinalized) {
  1095. whenFinalized();
  1096. }
  1097. }
  1098. };
  1099. BaseNode.prototype.baseFinalizeDeath = function () {
  1100. if (this._hookSubscribers) {
  1101. this._hookSubscribers.clearAll();
  1102. }
  1103. this._subpathUponDeath = this._subpath;
  1104. this._pathUponDeath = this.getEscapedPath(false);
  1105. this.baseSetParent(null, "");
  1106. this.state = NodeLifeCycle.DEAD;
  1107. };
  1108. BaseNode.prototype.baseAboutToDie = function () {
  1109. this.fireHook(Hook.beforeDestroy);
  1110. };
  1111. return BaseNode;
  1112. }());
  1113. /**
  1114. * @internal
  1115. * @hidden
  1116. */
  1117. var ScalarNode = /** @class */ (function (_super) {
  1118. __extends(ScalarNode, _super);
  1119. function ScalarNode(simpleType, parent, subpath, environment, initialSnapshot) {
  1120. var _this = _super.call(this, simpleType, parent, subpath, environment) || this;
  1121. try {
  1122. _this.storedValue = simpleType.createNewInstance(initialSnapshot);
  1123. }
  1124. catch (e) {
  1125. // short-cut to die the instance, to avoid the snapshot computed starting to throw...
  1126. _this.state = NodeLifeCycle.DEAD;
  1127. throw e;
  1128. }
  1129. _this.state = NodeLifeCycle.CREATED;
  1130. // for scalar nodes there's no point in firing this event since it would fire on the constructor, before
  1131. // anybody can actually register for/listen to it
  1132. // this.fireHook(Hook.AfterCreate)
  1133. _this.finalizeCreation();
  1134. return _this;
  1135. }
  1136. Object.defineProperty(ScalarNode.prototype, "root", {
  1137. get: function () {
  1138. // future optimization: store root ref in the node and maintain it
  1139. if (!this.parent)
  1140. throw fail$1("This scalar node is not part of a tree");
  1141. return this.parent.root;
  1142. },
  1143. enumerable: true,
  1144. configurable: true
  1145. });
  1146. ScalarNode.prototype.setParent = function (newParent, subpath) {
  1147. var parentChanged = this.parent !== newParent;
  1148. var subpathChanged = this.subpath !== subpath;
  1149. if (!parentChanged && !subpathChanged) {
  1150. return;
  1151. }
  1152. if (devMode()) {
  1153. if (!subpath) {
  1154. // istanbul ignore next
  1155. throw fail$1("assertion failed: subpath expected");
  1156. }
  1157. if (!newParent) {
  1158. // istanbul ignore next
  1159. throw fail$1("assertion failed: parent expected");
  1160. }
  1161. if (parentChanged) {
  1162. // istanbul ignore next
  1163. throw fail$1("assertion failed: scalar nodes cannot change their parent");
  1164. }
  1165. }
  1166. this.environment = undefined; // use parent's
  1167. this.baseSetParent(this.parent, subpath);
  1168. };
  1169. Object.defineProperty(ScalarNode.prototype, "snapshot", {
  1170. get: function () {
  1171. return freeze(this.getSnapshot());
  1172. },
  1173. enumerable: true,
  1174. configurable: true
  1175. });
  1176. ScalarNode.prototype.getSnapshot = function () {
  1177. return this.type.getSnapshot(this);
  1178. };
  1179. ScalarNode.prototype.toString = function () {
  1180. var path = (this.isAlive ? this.path : this.pathUponDeath) || "<root>";
  1181. return this.type.name + "@" + path + (this.isAlive ? "" : " [dead]");
  1182. };
  1183. ScalarNode.prototype.die = function () {
  1184. if (!this.isAlive || this.state === NodeLifeCycle.DETACHING)
  1185. return;
  1186. this.aboutToDie();
  1187. this.finalizeDeath();
  1188. };
  1189. ScalarNode.prototype.finalizeCreation = function () {
  1190. this.baseFinalizeCreation();
  1191. };
  1192. ScalarNode.prototype.aboutToDie = function () {
  1193. this.baseAboutToDie();
  1194. };
  1195. ScalarNode.prototype.finalizeDeath = function () {
  1196. this.baseFinalizeDeath();
  1197. };
  1198. ScalarNode.prototype.fireHook = function (name) {
  1199. this.fireInternalHook(name);
  1200. };
  1201. __decorate([
  1202. mobx.action
  1203. ], ScalarNode.prototype, "die", null);
  1204. return ScalarNode;
  1205. }(BaseNode));
  1206. var nextNodeId = 1;
  1207. var snapshotReactionOptions = {
  1208. onError: function (e) {
  1209. throw e;
  1210. }
  1211. };
  1212. /**
  1213. * @internal
  1214. * @hidden
  1215. */
  1216. var ObjectNode = /** @class */ (function (_super) {
  1217. __extends(ObjectNode, _super);
  1218. function ObjectNode(complexType, parent, subpath, environment, initialValue) {
  1219. var _this = _super.call(this, complexType, parent, subpath, environment) || this;
  1220. _this.nodeId = ++nextNodeId;
  1221. _this.isProtectionEnabled = true;
  1222. _this._autoUnbox = true; // unboxing is disabled when reading child nodes
  1223. _this._isRunningAction = false; // only relevant for root
  1224. _this._hasSnapshotReaction = false;
  1225. _this._observableInstanceState = 0 /* UNINITIALIZED */;
  1226. _this._cachedInitialSnapshotCreated = false;
  1227. _this.unbox = _this.unbox.bind(_this);
  1228. _this._initialSnapshot = freeze(initialValue);
  1229. _this.identifierAttribute = complexType.identifierAttribute;
  1230. if (!parent) {
  1231. _this.identifierCache = new IdentifierCache();
  1232. }
  1233. _this._childNodes = complexType.initializeChildNodes(_this, _this._initialSnapshot);
  1234. // identifier can not be changed during lifecycle of a node
  1235. // so we safely can read it from initial snapshot
  1236. _this.identifier = null;
  1237. _this.unnormalizedIdentifier = null;
  1238. if (_this.identifierAttribute && _this._initialSnapshot) {
  1239. var id = _this._initialSnapshot[_this.identifierAttribute];
  1240. if (id === undefined) {
  1241. // try with the actual node if not (for optional identifiers)
  1242. var childNode = _this._childNodes[_this.identifierAttribute];
  1243. if (childNode) {
  1244. id = childNode.value;
  1245. }
  1246. }
  1247. if (typeof id !== "string" && typeof id !== "number") {
  1248. throw fail$1("Instance identifier '" + _this.identifierAttribute + "' for type '" + _this.type.name + "' must be a string or a number");
  1249. }
  1250. // normalize internal identifier to string
  1251. _this.identifier = normalizeIdentifier(id);
  1252. _this.unnormalizedIdentifier = id;
  1253. }
  1254. if (!parent) {
  1255. _this.identifierCache.addNodeToCache(_this);
  1256. }
  1257. else {
  1258. parent.root.identifierCache.addNodeToCache(_this);
  1259. }
  1260. return _this;
  1261. }
  1262. ObjectNode.prototype.applyPatches = function (patches) {
  1263. this.createObservableInstanceIfNeeded();
  1264. this._applyPatches(patches);
  1265. };
  1266. ObjectNode.prototype.applySnapshot = function (snapshot) {
  1267. this.createObservableInstanceIfNeeded();
  1268. this._applySnapshot(snapshot);
  1269. };
  1270. ObjectNode.prototype.createObservableInstanceIfNeeded = function () {
  1271. var e_1, _a;
  1272. if (this._observableInstanceState !== 0 /* UNINITIALIZED */) {
  1273. return;
  1274. }
  1275. if (devMode()) {
  1276. if (this.state !== NodeLifeCycle.INITIALIZING) {
  1277. // istanbul ignore next
  1278. throw fail$1("assertion failed: the creation of the observable instance must be done on the initializing phase");
  1279. }
  1280. }
  1281. this._observableInstanceState = 1 /* CREATING */;
  1282. // make sure the parent chain is created as well
  1283. // array with parent chain from parent to child
  1284. var parentChain = [];
  1285. var parent = this.parent;
  1286. // for performance reasons we never go back further than the most direct
  1287. // uninitialized parent
  1288. // this is done to avoid traversing the whole tree to the root when using
  1289. // the same reference again
  1290. while (parent &&
  1291. parent._observableInstanceState === 0 /* UNINITIALIZED */) {
  1292. parentChain.unshift(parent);
  1293. parent = parent.parent;
  1294. }
  1295. try {
  1296. // initialize the uninitialized parent chain from parent to child
  1297. for (var parentChain_1 = __values(parentChain), parentChain_1_1 = parentChain_1.next(); !parentChain_1_1.done; parentChain_1_1 = parentChain_1.next()) {
  1298. var p = parentChain_1_1.value;
  1299. p.createObservableInstanceIfNeeded();
  1300. }
  1301. }
  1302. catch (e_1_1) { e_1 = { error: e_1_1 }; }
  1303. finally {
  1304. try {
  1305. if (parentChain_1_1 && !parentChain_1_1.done && (_a = parentChain_1.return)) _a.call(parentChain_1);
  1306. }
  1307. finally { if (e_1) throw e_1.error; }
  1308. }
  1309. var type = this.type;
  1310. try {
  1311. this.storedValue = type.createNewInstance(this._childNodes);
  1312. this.preboot();
  1313. this._isRunningAction = true;
  1314. type.finalizeNewInstance(this, this.storedValue);
  1315. }
  1316. catch (e) {
  1317. // short-cut to die the instance, to avoid the snapshot computed starting to throw...
  1318. this.state = NodeLifeCycle.DEAD;
  1319. throw e;
  1320. }
  1321. finally {
  1322. this._isRunningAction = false;
  1323. }
  1324. this._observableInstanceState = 2 /* CREATED */;
  1325. // NOTE: we need to touch snapshot, because non-observable
  1326. // "_observableInstanceState" field was touched
  1327. invalidateComputed(this, "snapshot");
  1328. if (this.isRoot)
  1329. this._addSnapshotReaction();
  1330. this._childNodes = EMPTY_OBJECT;
  1331. this.state = NodeLifeCycle.CREATED;
  1332. this.fireHook(Hook.afterCreate);
  1333. this.finalizeCreation();
  1334. };
  1335. Object.defineProperty(ObjectNode.prototype, "root", {
  1336. get: function () {
  1337. var parent = this.parent;
  1338. return parent ? parent.root : this;
  1339. },
  1340. enumerable: true,
  1341. configurable: true
  1342. });
  1343. ObjectNode.prototype.clearParent = function () {
  1344. if (!this.parent)
  1345. return;
  1346. // detach if attached
  1347. this.fireHook(Hook.beforeDetach);
  1348. var previousState = this.state;
  1349. this.state = NodeLifeCycle.DETACHING;
  1350. var root = this.root;
  1351. var newEnv = root.environment;
  1352. var newIdCache = root.identifierCache.splitCache(this);
  1353. try {
  1354. this.parent.removeChild(this.subpath);
  1355. this.baseSetParent(null, "");
  1356. this.environment = newEnv;
  1357. this.identifierCache = newIdCache;
  1358. }
  1359. finally {
  1360. this.state = previousState;
  1361. }
  1362. };
  1363. ObjectNode.prototype.setParent = function (newParent, subpath) {
  1364. var parentChanged = newParent !== this.parent;
  1365. var subpathChanged = subpath !== this.subpath;
  1366. if (!parentChanged && !subpathChanged) {
  1367. return;
  1368. }
  1369. if (devMode()) {
  1370. if (!subpath) {
  1371. // istanbul ignore next
  1372. throw fail$1("assertion failed: subpath expected");
  1373. }
  1374. if (!newParent) {
  1375. // istanbul ignore next
  1376. throw fail$1("assertion failed: new parent expected");
  1377. }
  1378. if (this.parent && parentChanged) {
  1379. throw fail$1("A node cannot exists twice in the state tree. Failed to add " + this + " to path '" + newParent.path + "/" + subpath + "'.");
  1380. }
  1381. if (!this.parent && newParent.root === this) {
  1382. throw fail$1("A state tree is not allowed to contain itself. Cannot assign " + this + " to path '" + newParent.path + "/" + subpath + "'");
  1383. }
  1384. if (!this.parent &&
  1385. !!this.environment &&
  1386. this.environment !== newParent.root.environment) {
  1387. throw fail$1("A state tree cannot be made part of another state tree as long as their environments are different.");
  1388. }
  1389. }
  1390. if (parentChanged) {
  1391. // attach to new parent
  1392. this.environment = undefined; // will use root's
  1393. newParent.root.identifierCache.mergeCache(this);
  1394. this.baseSetParent(newParent, subpath);
  1395. this.fireHook(Hook.afterAttach);
  1396. }
  1397. else if (subpathChanged) {
  1398. // moving to a new subpath on the same parent
  1399. this.baseSetParent(this.parent, subpath);
  1400. }
  1401. };
  1402. ObjectNode.prototype.fireHook = function (name) {
  1403. var _this = this;
  1404. this.fireInternalHook(name);
  1405. var fn = this.storedValue &&
  1406. typeof this.storedValue === "object" &&
  1407. this.storedValue[name];
  1408. if (typeof fn === "function") {
  1409. // we check for it to allow old mobx peer dependencies that don't have the method to work (even when still bugged)
  1410. if (mobx._allowStateChangesInsideComputed) {
  1411. mobx._allowStateChangesInsideComputed(function () {
  1412. fn.apply(_this.storedValue);
  1413. });
  1414. }
  1415. else {
  1416. fn.apply(this.storedValue);
  1417. }
  1418. }
  1419. };
  1420. Object.defineProperty(ObjectNode.prototype, "snapshot", {
  1421. // advantage of using computed for a snapshot is that nicely respects transactions etc.
  1422. get: function () {
  1423. return freeze(this.getSnapshot());
  1424. },
  1425. enumerable: true,
  1426. configurable: true
  1427. });
  1428. // NOTE: we use this method to get snapshot without creating @computed overhead
  1429. ObjectNode.prototype.getSnapshot = function () {
  1430. if (!this.isAlive)
  1431. return this._snapshotUponDeath;
  1432. return this._observableInstanceState === 2 /* CREATED */
  1433. ? this._getActualSnapshot()
  1434. : this._getCachedInitialSnapshot();
  1435. };
  1436. ObjectNode.prototype._getActualSnapshot = function () {
  1437. return this.type.getSnapshot(this);
  1438. };
  1439. ObjectNode.prototype._getCachedInitialSnapshot = function () {
  1440. if (!this._cachedInitialSnapshotCreated) {
  1441. var type = this.type;
  1442. var childNodes = this._childNodes;
  1443. var snapshot = this._initialSnapshot;
  1444. this._cachedInitialSnapshot = type.processInitialSnapshot(childNodes, snapshot);
  1445. this._cachedInitialSnapshotCreated = true;
  1446. }
  1447. return this._cachedInitialSnapshot;
  1448. };
  1449. ObjectNode.prototype.isRunningAction = function () {
  1450. if (this._isRunningAction)
  1451. return true;
  1452. if (this.isRoot)
  1453. return false;
  1454. return this.parent.isRunningAction();
  1455. };
  1456. ObjectNode.prototype.assertAlive = function (context) {
  1457. var livelinessChecking = getLivelinessChecking();
  1458. if (!this.isAlive && livelinessChecking !== "ignore") {
  1459. var error = this._getAssertAliveError(context);
  1460. switch (livelinessChecking) {
  1461. case "error":
  1462. throw fail$1(error);
  1463. case "warn":
  1464. warnError(error);
  1465. }
  1466. }
  1467. };
  1468. ObjectNode.prototype._getAssertAliveError = function (context) {
  1469. var escapedPath = this.getEscapedPath(false) || this.pathUponDeath || "";
  1470. var subpath = (context.subpath && escapeJsonPath(context.subpath)) || "";
  1471. var actionContext = context.actionContext || getCurrentActionContext();
  1472. // try to use a real action context if possible since it includes the action name
  1473. if (actionContext && actionContext.type !== "action" && actionContext.parentActionEvent) {
  1474. actionContext = actionContext.parentActionEvent;
  1475. }
  1476. var actionFullPath = "";
  1477. if (actionContext && actionContext.name != null) {
  1478. // try to use the context, and if it not available use the node one
  1479. var actionPath = (actionContext && actionContext.context && getPath(actionContext.context)) ||
  1480. escapedPath;
  1481. actionFullPath = actionPath + "." + actionContext.name + "()";
  1482. }
  1483. 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.";
  1484. };
  1485. ObjectNode.prototype.getChildNode = function (subpath) {
  1486. this.assertAlive({
  1487. subpath: subpath
  1488. });
  1489. this._autoUnbox = false;
  1490. try {
  1491. return this._observableInstanceState === 2 /* CREATED */
  1492. ? this.type.getChildNode(this, subpath)
  1493. : this._childNodes[subpath];
  1494. }
  1495. finally {
  1496. this._autoUnbox = true;
  1497. }
  1498. };
  1499. ObjectNode.prototype.getChildren = function () {
  1500. this.assertAlive(EMPTY_OBJECT);
  1501. this._autoUnbox = false;
  1502. try {
  1503. return this._observableInstanceState === 2 /* CREATED */
  1504. ? this.type.getChildren(this)
  1505. : convertChildNodesToArray(this._childNodes);
  1506. }
  1507. finally {
  1508. this._autoUnbox = true;
  1509. }
  1510. };
  1511. ObjectNode.prototype.getChildType = function (propertyName) {
  1512. return this.type.getChildType(propertyName);
  1513. };
  1514. Object.defineProperty(ObjectNode.prototype, "isProtected", {
  1515. get: function () {
  1516. return this.root.isProtectionEnabled;
  1517. },
  1518. enumerable: true,
  1519. configurable: true
  1520. });
  1521. ObjectNode.prototype.assertWritable = function (context) {
  1522. this.assertAlive(context);
  1523. if (!this.isRunningAction() && this.isProtected) {
  1524. throw fail$1("Cannot modify '" + this + "', the object is protected and can only be modified by using an action.");
  1525. }
  1526. };
  1527. ObjectNode.prototype.removeChild = function (subpath) {
  1528. this.type.removeChild(this, subpath);
  1529. };
  1530. // bound on the constructor
  1531. ObjectNode.prototype.unbox = function (childNode) {
  1532. if (!childNode)
  1533. return childNode;
  1534. this.assertAlive({
  1535. subpath: childNode.subpath || childNode.subpathUponDeath
  1536. });
  1537. return this._autoUnbox ? childNode.value : childNode;
  1538. };
  1539. ObjectNode.prototype.toString = function () {
  1540. var path = (this.isAlive ? this.path : this.pathUponDeath) || "<root>";
  1541. var identifier = this.identifier ? "(id: " + this.identifier + ")" : "";
  1542. return this.type.name + "@" + path + identifier + (this.isAlive ? "" : " [dead]");
  1543. };
  1544. ObjectNode.prototype.finalizeCreation = function () {
  1545. var _this = this;
  1546. this.baseFinalizeCreation(function () {
  1547. var e_2, _a;
  1548. try {
  1549. for (var _b = __values(_this.getChildren()), _c = _b.next(); !_c.done; _c = _b.next()) {
  1550. var child = _c.value;
  1551. child.finalizeCreation();
  1552. }
  1553. }
  1554. catch (e_2_1) { e_2 = { error: e_2_1 }; }
  1555. finally {
  1556. try {
  1557. if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
  1558. }
  1559. finally { if (e_2) throw e_2.error; }
  1560. }
  1561. _this.fireInternalHook(Hook.afterCreationFinalization);
  1562. });
  1563. };
  1564. ObjectNode.prototype.detach = function () {
  1565. if (!this.isAlive)
  1566. throw fail$1("Error while detaching, node is not alive.");
  1567. this.clearParent();
  1568. };
  1569. ObjectNode.prototype.preboot = function () {
  1570. var self = this;
  1571. this._applyPatches = createActionInvoker(this.storedValue, "@APPLY_PATCHES", function (patches) {
  1572. patches.forEach(function (patch) {
  1573. var parts = splitJsonPath(patch.path);
  1574. var node = resolveNodeByPathParts(self, parts.slice(0, -1));
  1575. node.applyPatchLocally(parts[parts.length - 1], patch);
  1576. });
  1577. });
  1578. this._applySnapshot = createActionInvoker(this.storedValue, "@APPLY_SNAPSHOT", function (snapshot) {
  1579. // if the snapshot is the same as the current one, avoid performing a reconcile
  1580. if (snapshot === self.snapshot)
  1581. return;
  1582. // else, apply it by calling the type logic
  1583. return self.type.applySnapshot(self, snapshot);
  1584. });
  1585. addHiddenFinalProp(this.storedValue, "$treenode", this);
  1586. addHiddenFinalProp(this.storedValue, "toJSON", toJSON);
  1587. };
  1588. ObjectNode.prototype.die = function () {
  1589. if (!this.isAlive || this.state === NodeLifeCycle.DETACHING)
  1590. return;
  1591. this.aboutToDie();
  1592. this.finalizeDeath();
  1593. };
  1594. ObjectNode.prototype.aboutToDie = function () {
  1595. if (this._observableInstanceState === 0 /* UNINITIALIZED */) {
  1596. return;
  1597. }
  1598. this.getChildren().forEach(function (node) {
  1599. node.aboutToDie();
  1600. });
  1601. // beforeDestroy should run before the disposers since else we could end up in a situation where
  1602. // a disposer added with addDisposer at this stage (beforeDestroy) is actually never released
  1603. this.baseAboutToDie();
  1604. this._internalEventsEmit("dispose" /* Dispose */);
  1605. this._internalEventsClear("dispose" /* Dispose */);
  1606. };
  1607. ObjectNode.prototype.finalizeDeath = function () {
  1608. // invariant: not called directly but from "die"
  1609. this.getChildren().forEach(function (node) {
  1610. node.finalizeDeath();
  1611. });
  1612. this.root.identifierCache.notifyDied(this);
  1613. // "kill" the computed prop and just store the last snapshot
  1614. var snapshot = this.snapshot;
  1615. this._snapshotUponDeath = snapshot;
  1616. this._internalEventsClearAll();
  1617. this.baseFinalizeDeath();
  1618. };
  1619. ObjectNode.prototype.onSnapshot = function (onChange) {
  1620. this._addSnapshotReaction();
  1621. return this._internalEventsRegister("snapshot" /* Snapshot */, onChange);
  1622. };
  1623. ObjectNode.prototype.emitSnapshot = function (snapshot) {
  1624. this._internalEventsEmit("snapshot" /* Snapshot */, snapshot);
  1625. };
  1626. ObjectNode.prototype.onPatch = function (handler) {
  1627. return this._internalEventsRegister("patch" /* Patch */, handler);
  1628. };
  1629. ObjectNode.prototype.emitPatch = function (basePatch, source) {
  1630. if (this._internalEventsHasSubscribers("patch" /* Patch */)) {
  1631. var localizedPatch = extend({}, basePatch, {
  1632. path: source.path.substr(this.path.length) + "/" + basePatch.path // calculate the relative path of the patch
  1633. });
  1634. var _a = __read(splitPatch(localizedPatch), 2), patch = _a[0], reversePatch = _a[1];
  1635. this._internalEventsEmit("patch" /* Patch */, patch, reversePatch);
  1636. }
  1637. if (this.parent)
  1638. this.parent.emitPatch(basePatch, source);
  1639. };
  1640. ObjectNode.prototype.hasDisposer = function (disposer) {
  1641. return this._internalEventsHas("dispose" /* Dispose */, disposer);
  1642. };
  1643. ObjectNode.prototype.addDisposer = function (disposer) {
  1644. if (!this.hasDisposer(disposer)) {
  1645. this._internalEventsRegister("dispose" /* Dispose */, disposer, true);
  1646. return;
  1647. }
  1648. throw fail$1("cannot add a disposer when it is already registered for execution");
  1649. };
  1650. ObjectNode.prototype.removeDisposer = function (disposer) {
  1651. if (!this._internalEventsHas("dispose" /* Dispose */, disposer)) {
  1652. throw fail$1("cannot remove a disposer which was never registered for execution");
  1653. }
  1654. this._internalEventsUnregister("dispose" /* Dispose */, disposer);
  1655. };
  1656. ObjectNode.prototype.removeMiddleware = function (middleware) {
  1657. if (this.middlewares) {
  1658. var index = this.middlewares.indexOf(middleware);
  1659. if (index >= 0) {
  1660. this.middlewares.splice(index, 1);
  1661. }
  1662. }
  1663. };
  1664. ObjectNode.prototype.addMiddleWare = function (handler, includeHooks) {
  1665. var _this = this;
  1666. if (includeHooks === void 0) { includeHooks = true; }
  1667. var middleware = { handler: handler, includeHooks: includeHooks };
  1668. if (!this.middlewares)
  1669. this.middlewares = [middleware];
  1670. else
  1671. this.middlewares.push(middleware);
  1672. return function () {
  1673. _this.removeMiddleware(middleware);
  1674. };
  1675. };
  1676. ObjectNode.prototype.applyPatchLocally = function (subpath, patch) {
  1677. this.assertWritable({
  1678. subpath: subpath
  1679. });
  1680. this.createObservableInstanceIfNeeded();
  1681. this.type.applyPatchLocally(this, subpath, patch);
  1682. };
  1683. ObjectNode.prototype._addSnapshotReaction = function () {
  1684. var _this = this;
  1685. if (!this._hasSnapshotReaction) {
  1686. var snapshotDisposer = mobx.reaction(function () { return _this.snapshot; }, function (snapshot) { return _this.emitSnapshot(snapshot); }, snapshotReactionOptions);
  1687. this.addDisposer(snapshotDisposer);
  1688. this._hasSnapshotReaction = true;
  1689. }
  1690. };
  1691. // we proxy the methods to avoid creating an EventHandlers instance when it is not needed
  1692. ObjectNode.prototype._internalEventsHasSubscribers = function (event) {
  1693. return !!this._internalEvents && this._internalEvents.hasSubscribers(event);
  1694. };
  1695. ObjectNode.prototype._internalEventsRegister = function (event, eventHandler, atTheBeginning) {
  1696. if (atTheBeginning === void 0) { atTheBeginning = false; }
  1697. if (!this._internalEvents) {
  1698. this._internalEvents = new EventHandlers();
  1699. }
  1700. return this._internalEvents.register(event, eventHandler, atTheBeginning);
  1701. };
  1702. ObjectNode.prototype._internalEventsHas = function (event, eventHandler) {
  1703. return !!this._internalEvents && this._internalEvents.has(event, eventHandler);
  1704. };
  1705. ObjectNode.prototype._internalEventsUnregister = function (event, eventHandler) {
  1706. if (this._internalEvents) {
  1707. this._internalEvents.unregister(event, eventHandler);
  1708. }
  1709. };
  1710. ObjectNode.prototype._internalEventsEmit = function (event) {
  1711. var _a;
  1712. var args = [];
  1713. for (var _i = 1; _i < arguments.length; _i++) {
  1714. args[_i - 1] = arguments[_i];
  1715. }
  1716. if (this._internalEvents) {
  1717. (_a = this._internalEvents).emit.apply(_a, __spread([event], args));
  1718. }
  1719. };
  1720. ObjectNode.prototype._internalEventsClear = function (event) {
  1721. if (this._internalEvents) {
  1722. this._internalEvents.clear(event);
  1723. }
  1724. };
  1725. ObjectNode.prototype._internalEventsClearAll = function () {
  1726. if (this._internalEvents) {
  1727. this._internalEvents.clearAll();
  1728. }
  1729. };
  1730. __decorate([
  1731. mobx.action
  1732. ], ObjectNode.prototype, "createObservableInstanceIfNeeded", null);
  1733. __decorate([
  1734. mobx.computed
  1735. ], ObjectNode.prototype, "snapshot", null);
  1736. __decorate([
  1737. mobx.action
  1738. ], ObjectNode.prototype, "detach", null);
  1739. __decorate([
  1740. mobx.action
  1741. ], ObjectNode.prototype, "die", null);
  1742. return ObjectNode;
  1743. }(BaseNode));
  1744. /**
  1745. * @internal
  1746. * @hidden
  1747. */
  1748. var TypeFlags;
  1749. (function (TypeFlags) {
  1750. TypeFlags[TypeFlags["String"] = 1] = "String";
  1751. TypeFlags[TypeFlags["Number"] = 2] = "Number";
  1752. TypeFlags[TypeFlags["Boolean"] = 4] = "Boolean";
  1753. TypeFlags[TypeFlags["Date"] = 8] = "Date";
  1754. TypeFlags[TypeFlags["Literal"] = 16] = "Literal";
  1755. TypeFlags[TypeFlags["Array"] = 32] = "Array";
  1756. TypeFlags[TypeFlags["Map"] = 64] = "Map";
  1757. TypeFlags[TypeFlags["Object"] = 128] = "Object";
  1758. TypeFlags[TypeFlags["Frozen"] = 256] = "Frozen";
  1759. TypeFlags[TypeFlags["Optional"] = 512] = "Optional";
  1760. TypeFlags[TypeFlags["Reference"] = 1024] = "Reference";
  1761. TypeFlags[TypeFlags["Identifier"] = 2048] = "Identifier";
  1762. TypeFlags[TypeFlags["Late"] = 4096] = "Late";
  1763. TypeFlags[TypeFlags["Refinement"] = 8192] = "Refinement";
  1764. TypeFlags[TypeFlags["Union"] = 16384] = "Union";
  1765. TypeFlags[TypeFlags["Null"] = 32768] = "Null";
  1766. TypeFlags[TypeFlags["Undefined"] = 65536] = "Undefined";
  1767. TypeFlags[TypeFlags["Integer"] = 131072] = "Integer";
  1768. TypeFlags[TypeFlags["Custom"] = 262144] = "Custom";
  1769. TypeFlags[TypeFlags["SnapshotProcessor"] = 524288] = "SnapshotProcessor";
  1770. })(TypeFlags || (TypeFlags = {}));
  1771. /**
  1772. * @internal
  1773. * @hidden
  1774. */
  1775. var cannotDetermineSubtype = "cannotDetermine";
  1776. /**
  1777. * A base type produces a MST node (Node in the state tree)
  1778. *
  1779. * @internal
  1780. * @hidden
  1781. */
  1782. var BaseType = /** @class */ (function () {
  1783. function BaseType(name) {
  1784. this.isType = true;
  1785. this.name = name;
  1786. }
  1787. BaseType.prototype.create = function (snapshot, environment) {
  1788. typecheckInternal(this, snapshot);
  1789. return this.instantiate(null, "", environment, snapshot).value;
  1790. };
  1791. BaseType.prototype.getSnapshot = function (node, applyPostProcess) {
  1792. // istanbul ignore next
  1793. throw fail$1("unimplemented method");
  1794. };
  1795. BaseType.prototype.isAssignableFrom = function (type) {
  1796. return type === this;
  1797. };
  1798. BaseType.prototype.validate = function (value, context) {
  1799. var node = getStateTreeNodeSafe(value);
  1800. if (node) {
  1801. var valueType = getType(value);
  1802. return this.isAssignableFrom(valueType)
  1803. ? typeCheckSuccess()
  1804. : typeCheckFailure(context, value);
  1805. // it is tempting to compare snapshots, but in that case we should always clone on assignments...
  1806. }
  1807. return this.isValidSnapshot(value, context);
  1808. };
  1809. BaseType.prototype.is = function (thing) {
  1810. return this.validate(thing, [{ path: "", type: this }]).length === 0;
  1811. };
  1812. Object.defineProperty(BaseType.prototype, "Type", {
  1813. get: function () {
  1814. // istanbul ignore next
  1815. 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`");
  1816. },
  1817. enumerable: true,
  1818. configurable: true
  1819. });
  1820. Object.defineProperty(BaseType.prototype, "TypeWithoutSTN", {
  1821. get: function () {
  1822. // istanbul ignore next
  1823. 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`");
  1824. },
  1825. enumerable: true,
  1826. configurable: true
  1827. });
  1828. Object.defineProperty(BaseType.prototype, "SnapshotType", {
  1829. get: function () {
  1830. // istanbul ignore next
  1831. 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`");
  1832. },
  1833. enumerable: true,
  1834. configurable: true
  1835. });
  1836. Object.defineProperty(BaseType.prototype, "CreationType", {
  1837. get: function () {
  1838. // istanbul ignore next
  1839. 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`");
  1840. },
  1841. enumerable: true,
  1842. configurable: true
  1843. });
  1844. __decorate([
  1845. mobx.action
  1846. ], BaseType.prototype, "create", null);
  1847. return BaseType;
  1848. }());
  1849. /**
  1850. * A complex type produces a MST node (Node in the state tree)
  1851. *
  1852. * @internal
  1853. * @hidden
  1854. */
  1855. var ComplexType = /** @class */ (function (_super) {
  1856. __extends(ComplexType, _super);
  1857. function ComplexType(name) {
  1858. return _super.call(this, name) || this;
  1859. }
  1860. ComplexType.prototype.create = function (snapshot, environment) {
  1861. if (snapshot === void 0) { snapshot = this.getDefaultSnapshot(); }
  1862. return _super.prototype.create.call(this, snapshot, environment);
  1863. };
  1864. ComplexType.prototype.getValue = function (node) {
  1865. node.createObservableInstanceIfNeeded();
  1866. return node.storedValue;
  1867. };
  1868. ComplexType.prototype.tryToReconcileNode = function (current, newValue) {
  1869. if (current.isDetaching)
  1870. return false;
  1871. if (current.snapshot === newValue) {
  1872. // newValue is the current snapshot of the node, noop
  1873. return true;
  1874. }
  1875. if (isStateTreeNode(newValue) && getStateTreeNode(newValue) === current) {
  1876. // the current node is the same as the new one
  1877. return true;
  1878. }
  1879. if (current.type === this &&
  1880. isMutable(newValue) &&
  1881. !isStateTreeNode(newValue) &&
  1882. (!current.identifierAttribute ||
  1883. current.identifier ===
  1884. normalizeIdentifier(newValue[current.identifierAttribute]))) {
  1885. // the newValue has no node, so can be treated like a snapshot
  1886. // we can reconcile
  1887. current.applySnapshot(newValue);
  1888. return true;
  1889. }
  1890. return false;
  1891. };
  1892. ComplexType.prototype.reconcile = function (current, newValue, parent, subpath) {
  1893. var nodeReconciled = this.tryToReconcileNode(current, newValue);
  1894. if (nodeReconciled) {
  1895. current.setParent(parent, subpath);
  1896. return current;
  1897. }
  1898. // current node cannot be recycled in any way
  1899. current.die(); // noop if detaching
  1900. // attempt to reuse the new one
  1901. if (isStateTreeNode(newValue) && this.isAssignableFrom(getType(newValue))) {
  1902. // newValue is a Node as well, move it here..
  1903. var newNode = getStateTreeNode(newValue);
  1904. newNode.setParent(parent, subpath);
  1905. return newNode;
  1906. }
  1907. // nothing to do, we have to create a new node
  1908. return this.instantiate(parent, subpath, undefined, newValue);
  1909. };
  1910. ComplexType.prototype.getSubTypes = function () {
  1911. return null;
  1912. };
  1913. __decorate([
  1914. mobx.action
  1915. ], ComplexType.prototype, "create", null);
  1916. return ComplexType;
  1917. }(BaseType));
  1918. /**
  1919. * @internal
  1920. * @hidden
  1921. */
  1922. var SimpleType = /** @class */ (function (_super) {
  1923. __extends(SimpleType, _super);
  1924. function SimpleType() {
  1925. return _super !== null && _super.apply(this, arguments) || this;
  1926. }
  1927. SimpleType.prototype.createNewInstance = function (snapshot) {
  1928. return snapshot;
  1929. };
  1930. SimpleType.prototype.getValue = function (node) {
  1931. // if we ever find a case where scalar nodes can be accessed without iterating through its parent
  1932. // uncomment this to make sure the parent chain is created when this is accessed
  1933. // if (node.parent) {
  1934. // node.parent.createObservableInstanceIfNeeded()
  1935. // }
  1936. return node.storedValue;
  1937. };
  1938. SimpleType.prototype.getSnapshot = function (node) {
  1939. return node.storedValue;
  1940. };
  1941. SimpleType.prototype.reconcile = function (current, newValue, parent, subpath) {
  1942. // reconcile only if type and value are still the same, and only if the node is not detaching
  1943. if (!current.isDetaching && current.type === this && current.storedValue === newValue) {
  1944. return current;
  1945. }
  1946. var res = this.instantiate(parent, subpath, undefined, newValue);
  1947. current.die(); // noop if detaching
  1948. return res;
  1949. };
  1950. SimpleType.prototype.getSubTypes = function () {
  1951. return null;
  1952. };
  1953. return SimpleType;
  1954. }(BaseType));
  1955. /**
  1956. * Returns if a given value represents a type.
  1957. *
  1958. * @param value Value to check.
  1959. * @returns `true` if the value is a type.
  1960. */
  1961. function isType(value) {
  1962. return typeof value === "object" && value && value.isType === true;
  1963. }
  1964. /**
  1965. * @internal
  1966. * @hidden
  1967. */
  1968. function assertIsType(type, argNumber) {
  1969. assertArg(type, isType, "mobx-state-tree type", argNumber);
  1970. }
  1971. var runningActions = new Map();
  1972. /**
  1973. * Note: Consider migrating to `createActionTrackingMiddleware2`, it is easier to use.
  1974. *
  1975. * Convenience utility to create action based middleware that supports async processes more easily.
  1976. * All hooks are called for both synchronous and asynchronous actions. Except that either `onSuccess` or `onFail` is called
  1977. *
  1978. * The create middleware tracks the process of an action (assuming it passes the `filter`).
  1979. * `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.
  1980. *
  1981. * See the `atomic` middleware for an example
  1982. *
  1983. * @param hooks
  1984. * @returns
  1985. */
  1986. function createActionTrackingMiddleware(hooks) {
  1987. return function actionTrackingMiddleware(call, next, abort) {
  1988. switch (call.type) {
  1989. case "action": {
  1990. if (!hooks.filter || hooks.filter(call) === true) {
  1991. var context = hooks.onStart(call);
  1992. hooks.onResume(call, context);
  1993. runningActions.set(call.id, {
  1994. call: call,
  1995. context: context,
  1996. async: false
  1997. });
  1998. try {
  1999. var res = next(call);
  2000. hooks.onSuspend(call, context);
  2001. if (runningActions.get(call.id).async === false) {
  2002. runningActions.delete(call.id);
  2003. hooks.onSuccess(call, context, res);
  2004. }
  2005. return res;
  2006. }
  2007. catch (e) {
  2008. runningActions.delete(call.id);
  2009. hooks.onFail(call, context, e);
  2010. throw e;
  2011. }
  2012. }
  2013. else {
  2014. return next(call);
  2015. }
  2016. }
  2017. case "flow_spawn": {
  2018. var root = runningActions.get(call.rootId);
  2019. root.async = true;
  2020. return next(call);
  2021. }
  2022. case "flow_resume":
  2023. case "flow_resume_error": {
  2024. var root = runningActions.get(call.rootId);
  2025. hooks.onResume(call, root.context);
  2026. try {
  2027. return next(call);
  2028. }
  2029. finally {
  2030. hooks.onSuspend(call, root.context);
  2031. }
  2032. }
  2033. case "flow_throw": {
  2034. var root = runningActions.get(call.rootId);
  2035. runningActions.delete(call.rootId);
  2036. hooks.onFail(call, root.context, call.args[0]);
  2037. return next(call);
  2038. }
  2039. case "flow_return": {
  2040. var root = runningActions.get(call.rootId);
  2041. runningActions.delete(call.rootId);
  2042. hooks.onSuccess(call, root.context, call.args[0]);
  2043. return next(call);
  2044. }
  2045. }
  2046. };
  2047. }
  2048. var RunningAction = /** @class */ (function () {
  2049. function RunningAction(hooks, call) {
  2050. this.hooks = hooks;
  2051. this.call = call;
  2052. this.flowsPending = 0;
  2053. this.running = true;
  2054. if (hooks) {
  2055. hooks.onStart(call);
  2056. }
  2057. }
  2058. RunningAction.prototype.finish = function (error) {
  2059. if (this.running) {
  2060. this.running = false;
  2061. if (this.hooks) {
  2062. this.hooks.onFinish(this.call, error);
  2063. }
  2064. }
  2065. };
  2066. RunningAction.prototype.incFlowsPending = function () {
  2067. this.flowsPending++;
  2068. };
  2069. RunningAction.prototype.decFlowsPending = function () {
  2070. this.flowsPending--;
  2071. };
  2072. Object.defineProperty(RunningAction.prototype, "hasFlowsPending", {
  2073. get: function () {
  2074. return this.flowsPending > 0;
  2075. },
  2076. enumerable: true,
  2077. configurable: true
  2078. });
  2079. return RunningAction;
  2080. }());
  2081. /**
  2082. * Convenience utility to create action based middleware that supports async processes more easily.
  2083. * The flow is like this:
  2084. * - for each action: if filter passes -> `onStart` -> (inner actions recursively) -> `onFinish`
  2085. *
  2086. * Example: if we had an action `a` that called inside an action `b1`, then `b2` the flow would be:
  2087. * - `filter(a)`
  2088. * - `onStart(a)`
  2089. * - `filter(b1)`
  2090. * - `onStart(b1)`
  2091. * - `onFinish(b1)`
  2092. * - `filter(b2)`
  2093. * - `onStart(b2)`
  2094. * - `onFinish(b2)`
  2095. * - `onFinish(a)`
  2096. *
  2097. * The flow is the same no matter if the actions are sync or async.
  2098. *
  2099. * See the `atomic` middleware for an example
  2100. *
  2101. * @param hooks
  2102. * @returns
  2103. */
  2104. function createActionTrackingMiddleware2(middlewareHooks) {
  2105. var runningActions = new WeakMap();
  2106. return function actionTrackingMiddleware(call, next) {
  2107. // find parentRunningAction
  2108. var parentRunningAction = call.parentActionEvent
  2109. ? runningActions.get(call.parentActionEvent)
  2110. : undefined;
  2111. if (call.type === "action") {
  2112. var newCall = __assign(__assign({}, call), {
  2113. // make a shallow copy of the parent action env
  2114. env: parentRunningAction && parentRunningAction.call.env, parentCall: parentRunningAction && parentRunningAction.call });
  2115. var passesFilter = !middlewareHooks.filter || middlewareHooks.filter(newCall);
  2116. var hooks = passesFilter ? middlewareHooks : undefined;
  2117. var runningAction = new RunningAction(hooks, newCall);
  2118. runningActions.set(call, runningAction);
  2119. var res = void 0;
  2120. try {
  2121. res = next(call);
  2122. }
  2123. catch (e) {
  2124. runningAction.finish(e);
  2125. throw e;
  2126. }
  2127. if (!runningAction.hasFlowsPending) {
  2128. // sync action finished
  2129. runningAction.finish();
  2130. }
  2131. return res;
  2132. }
  2133. else {
  2134. if (!parentRunningAction) {
  2135. return next(call);
  2136. }
  2137. switch (call.type) {
  2138. case "flow_spawn": {
  2139. parentRunningAction.incFlowsPending();
  2140. return next(call);
  2141. }
  2142. case "flow_resume":
  2143. case "flow_resume_error": {
  2144. return next(call);
  2145. }
  2146. case "flow_throw": {
  2147. var error = call.args[0];
  2148. try {
  2149. return next(call);
  2150. }
  2151. finally {
  2152. parentRunningAction.decFlowsPending();
  2153. if (!parentRunningAction.hasFlowsPending) {
  2154. parentRunningAction.finish(error);
  2155. }
  2156. }
  2157. }
  2158. case "flow_return": {
  2159. try {
  2160. return next(call);
  2161. }
  2162. finally {
  2163. parentRunningAction.decFlowsPending();
  2164. if (!parentRunningAction.hasFlowsPending) {
  2165. parentRunningAction.finish();
  2166. }
  2167. }
  2168. }
  2169. }
  2170. }
  2171. };
  2172. }
  2173. function serializeArgument(node, actionName, index, arg) {
  2174. if (arg instanceof Date)
  2175. return { $MST_DATE: arg.getTime() };
  2176. if (isPrimitive(arg))
  2177. return arg;
  2178. // 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
  2179. // 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
  2180. if (isStateTreeNode(arg))
  2181. return serializeTheUnserializable("[MSTNode: " + getType(arg).name + "]");
  2182. if (typeof arg === "function")
  2183. return serializeTheUnserializable("[function]");
  2184. if (typeof arg === "object" && !isPlainObject(arg) && !isArray(arg))
  2185. return serializeTheUnserializable("[object " + ((arg && arg.constructor && arg.constructor.name) ||
  2186. "Complex Object") + "]");
  2187. try {
  2188. // Check if serializable, cycle free etc...
  2189. // MWE: there must be a better way....
  2190. JSON.stringify(arg); // or throws
  2191. return arg;
  2192. }
  2193. catch (e) {
  2194. return serializeTheUnserializable("" + e);
  2195. }
  2196. }
  2197. function deserializeArgument(adm, value) {
  2198. if (value && typeof value === "object" && "$MST_DATE" in value)
  2199. return new Date(value["$MST_DATE"]);
  2200. return value;
  2201. }
  2202. function serializeTheUnserializable(baseType) {
  2203. return {
  2204. $MST_UNSERIALIZABLE: true,
  2205. type: baseType
  2206. };
  2207. }
  2208. /**
  2209. * Applies an action or a series of actions in a single MobX transaction.
  2210. * Does not return any value
  2211. * Takes an action description as produced by the `onAction` middleware.
  2212. *
  2213. * @param target
  2214. * @param actions
  2215. */
  2216. function applyAction(target, actions) {
  2217. // check all arguments
  2218. assertIsStateTreeNode(target, 1);
  2219. assertArg(actions, function (a) { return typeof a === "object"; }, "object or array", 2);
  2220. mobx.runInAction(function () {
  2221. asArray(actions).forEach(function (action) { return baseApplyAction(target, action); });
  2222. });
  2223. }
  2224. function baseApplyAction(target, action) {
  2225. var resolvedTarget = tryResolve(target, action.path || "");
  2226. if (!resolvedTarget)
  2227. throw fail$1("Invalid action path: " + (action.path || ""));
  2228. var node = getStateTreeNode(resolvedTarget);
  2229. // Reserved functions
  2230. if (action.name === "@APPLY_PATCHES") {
  2231. return applyPatch.call(null, resolvedTarget, action.args[0]);
  2232. }
  2233. if (action.name === "@APPLY_SNAPSHOT") {
  2234. return applySnapshot.call(null, resolvedTarget, action.args[0]);
  2235. }
  2236. if (!(typeof resolvedTarget[action.name] === "function"))
  2237. throw fail$1("Action '" + action.name + "' does not exist in '" + node.path + "'");
  2238. return resolvedTarget[action.name].apply(resolvedTarget, action.args ? action.args.map(function (v) { return deserializeArgument(node, v); }) : []);
  2239. }
  2240. /**
  2241. * Small abstraction around `onAction` and `applyAction`, attaches an action listener to a tree and records all the actions emitted.
  2242. * Returns an recorder object with the following signature:
  2243. *
  2244. * Example:
  2245. * ```ts
  2246. * export interface IActionRecorder {
  2247. * // the recorded actions
  2248. * actions: ISerializedActionCall[]
  2249. * // true if currently recording
  2250. * recording: boolean
  2251. * // stop recording actions
  2252. * stop(): void
  2253. * // resume recording actions
  2254. * resume(): void
  2255. * // apply all the recorded actions on the given object
  2256. * replay(target: IAnyStateTreeNode): void
  2257. * }
  2258. * ```
  2259. *
  2260. * The optional filter function allows to skip recording certain actions.
  2261. *
  2262. * @param subject
  2263. * @returns
  2264. */
  2265. function recordActions(subject, filter) {
  2266. // check all arguments
  2267. assertIsStateTreeNode(subject, 1);
  2268. var actions = [];
  2269. var listener = function (call) {
  2270. var recordThis = filter ? filter(call, getRunningActionContext()) : true;
  2271. if (recordThis) {
  2272. actions.push(call);
  2273. }
  2274. };
  2275. var disposer;
  2276. var recorder = {
  2277. actions: actions,
  2278. get recording() {
  2279. return !!disposer;
  2280. },
  2281. stop: function () {
  2282. if (disposer) {
  2283. disposer();
  2284. disposer = undefined;
  2285. }
  2286. },
  2287. resume: function () {
  2288. if (disposer)
  2289. return;
  2290. disposer = onAction(subject, listener);
  2291. },
  2292. replay: function (target) {
  2293. applyAction(target, actions);
  2294. }
  2295. };
  2296. recorder.resume();
  2297. return recorder;
  2298. }
  2299. /**
  2300. * Registers a function that will be invoked for each action that is called on the provided model instance, or to any of its children.
  2301. * 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.
  2302. * Action can also be intercepted by middleware using addMiddleware to change the function call before it will be run.
  2303. *
  2304. * Not all action arguments might be serializable. For unserializable arguments, a struct like `{ $MST_UNSERIALIZABLE: true, type: "someType" }` will be generated.
  2305. * 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).
  2306. * 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.
  2307. *
  2308. * Example:
  2309. * ```ts
  2310. * const Todo = types.model({
  2311. * task: types.string
  2312. * })
  2313. *
  2314. * const TodoStore = types.model({
  2315. * todos: types.array(Todo)
  2316. * }).actions(self => ({
  2317. * add(todo) {
  2318. * self.todos.push(todo);
  2319. * }
  2320. * }))
  2321. *
  2322. * const s = TodoStore.create({ todos: [] })
  2323. *
  2324. * let disposer = onAction(s, (call) => {
  2325. * console.log(call);
  2326. * })
  2327. *
  2328. * s.add({ task: "Grab a coffee" })
  2329. * // Logs: { name: "add", path: "", args: [{ task: "Grab a coffee" }] }
  2330. * ```
  2331. *
  2332. * @param target
  2333. * @param listener
  2334. * @param attachAfter (default false) fires the listener *after* the action has executed instead of before.
  2335. * @returns
  2336. */
  2337. function onAction(target, listener, attachAfter) {
  2338. if (attachAfter === void 0) { attachAfter = false; }
  2339. // check all arguments
  2340. assertIsStateTreeNode(target, 1);
  2341. if (devMode()) {
  2342. if (!isRoot(target))
  2343. warnError("Warning: Attaching onAction listeners to non root nodes is dangerous: No events will be emitted for actions initiated higher up in the tree.");
  2344. if (!isProtected(target))
  2345. warnError("Warning: Attaching onAction listeners to non protected nodes is dangerous: No events will be emitted for direct modifications without action.");
  2346. }
  2347. return addMiddleware(target, function handler(rawCall, next) {
  2348. if (rawCall.type === "action" && rawCall.id === rawCall.rootId) {
  2349. var sourceNode_1 = getStateTreeNode(rawCall.context);
  2350. var info = {
  2351. name: rawCall.name,
  2352. path: getRelativePathBetweenNodes(getStateTreeNode(target), sourceNode_1),
  2353. args: rawCall.args.map(function (arg, index) {
  2354. return serializeArgument(sourceNode_1, rawCall.name, index, arg);
  2355. })
  2356. };
  2357. if (attachAfter) {
  2358. var res = next(rawCall);
  2359. listener(info);
  2360. return res;
  2361. }
  2362. else {
  2363. listener(info);
  2364. return next(rawCall);
  2365. }
  2366. }
  2367. else {
  2368. return next(rawCall);
  2369. }
  2370. });
  2371. }
  2372. var nextActionId = 1;
  2373. var currentActionContext;
  2374. /**
  2375. * @internal
  2376. * @hidden
  2377. */
  2378. function getCurrentActionContext() {
  2379. return currentActionContext;
  2380. }
  2381. /**
  2382. * @internal
  2383. * @hidden
  2384. */
  2385. function getNextActionId() {
  2386. return nextActionId++;
  2387. }
  2388. // TODO: optimize away entire action context if there is no middleware in tree?
  2389. /**
  2390. * @internal
  2391. * @hidden
  2392. */
  2393. function runWithActionContext(context, fn) {
  2394. var node = getStateTreeNode(context.context);
  2395. if (context.type === "action") {
  2396. node.assertAlive({
  2397. actionContext: context
  2398. });
  2399. }
  2400. var baseIsRunningAction = node._isRunningAction;
  2401. node._isRunningAction = true;
  2402. var previousContext = currentActionContext;
  2403. currentActionContext = context;
  2404. try {
  2405. return runMiddleWares(node, context, fn);
  2406. }
  2407. finally {
  2408. currentActionContext = previousContext;
  2409. node._isRunningAction = baseIsRunningAction;
  2410. }
  2411. }
  2412. /**
  2413. * @internal
  2414. * @hidden
  2415. */
  2416. function getParentActionContext(parentContext) {
  2417. if (!parentContext)
  2418. return undefined;
  2419. if (parentContext.type === "action")
  2420. return parentContext;
  2421. return parentContext.parentActionEvent;
  2422. }
  2423. /**
  2424. * @internal
  2425. * @hidden
  2426. */
  2427. function createActionInvoker(target, name, fn) {
  2428. var res = function () {
  2429. var id = getNextActionId();
  2430. var parentContext = currentActionContext;
  2431. var parentActionContext = getParentActionContext(parentContext);
  2432. return runWithActionContext({
  2433. type: "action",
  2434. name: name,
  2435. id: id,
  2436. args: argsToArray(arguments),
  2437. context: target,
  2438. tree: getRoot(target),
  2439. rootId: parentContext ? parentContext.rootId : id,
  2440. parentId: parentContext ? parentContext.id : 0,
  2441. allParentIds: parentContext
  2442. ? __spread(parentContext.allParentIds, [parentContext.id]) : [],
  2443. parentEvent: parentContext,
  2444. parentActionEvent: parentActionContext
  2445. }, fn);
  2446. };
  2447. res._isMSTAction = true;
  2448. return res;
  2449. }
  2450. /**
  2451. * Middleware can be used to intercept any action is invoked on the subtree where it is attached.
  2452. * If a tree is protected (by default), this means that any mutation of the tree will pass through your middleware.
  2453. *
  2454. * For more details, see the [middleware docs](../middleware.md)
  2455. *
  2456. * @param target Node to apply the middleware to.
  2457. * @param middleware Middleware to apply.
  2458. * @returns A callable function to dispose the middleware.
  2459. */
  2460. function addMiddleware(target, handler, includeHooks) {
  2461. if (includeHooks === void 0) { includeHooks = true; }
  2462. var node = getStateTreeNode(target);
  2463. if (devMode()) {
  2464. if (!node.isProtectionEnabled) {
  2465. 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`");
  2466. }
  2467. }
  2468. return node.addMiddleWare(handler, includeHooks);
  2469. }
  2470. /**
  2471. * Binds middleware to a specific action.
  2472. *
  2473. * Example:
  2474. * ```ts
  2475. * type.actions(self => {
  2476. * function takeA____() {
  2477. * self.toilet.donate()
  2478. * self.wipe()
  2479. * self.wipe()
  2480. * self.toilet.flush()
  2481. * }
  2482. * return {
  2483. * takeA____: decorate(atomic, takeA____)
  2484. * }
  2485. * })
  2486. * ```
  2487. *
  2488. * @param handler
  2489. * @param fn
  2490. * @param includeHooks
  2491. * @returns The original function
  2492. */
  2493. function decorate(handler, fn, includeHooks) {
  2494. if (includeHooks === void 0) { includeHooks = true; }
  2495. var middleware = { handler: handler, includeHooks: includeHooks };
  2496. fn.$mst_middleware = fn.$mst_middleware || [];
  2497. fn.$mst_middleware.push(middleware);
  2498. return fn;
  2499. }
  2500. var CollectedMiddlewares = /** @class */ (function () {
  2501. function CollectedMiddlewares(node, fn) {
  2502. this.arrayIndex = 0;
  2503. this.inArrayIndex = 0;
  2504. this.middlewares = [];
  2505. // we just push middleware arrays into an array of arrays to avoid making copies
  2506. if (fn.$mst_middleware) {
  2507. this.middlewares.push(fn.$mst_middleware);
  2508. }
  2509. var n = node;
  2510. // Find all middlewares. Optimization: cache this?
  2511. while (n) {
  2512. if (n.middlewares)
  2513. this.middlewares.push(n.middlewares);
  2514. n = n.parent;
  2515. }
  2516. }
  2517. Object.defineProperty(CollectedMiddlewares.prototype, "isEmpty", {
  2518. get: function () {
  2519. return this.middlewares.length <= 0;
  2520. },
  2521. enumerable: true,
  2522. configurable: true
  2523. });
  2524. CollectedMiddlewares.prototype.getNextMiddleware = function () {
  2525. var array = this.middlewares[this.arrayIndex];
  2526. if (!array)
  2527. return undefined;
  2528. var item = array[this.inArrayIndex++];
  2529. if (!item) {
  2530. this.arrayIndex++;
  2531. this.inArrayIndex = 0;
  2532. return this.getNextMiddleware();
  2533. }
  2534. return item;
  2535. };
  2536. return CollectedMiddlewares;
  2537. }());
  2538. function runMiddleWares(node, baseCall, originalFn) {
  2539. var middlewares = new CollectedMiddlewares(node, originalFn);
  2540. // Short circuit
  2541. if (middlewares.isEmpty)
  2542. return mobx.action(originalFn).apply(null, baseCall.args);
  2543. var result = null;
  2544. function runNextMiddleware(call) {
  2545. var middleware = middlewares.getNextMiddleware();
  2546. var handler = middleware && middleware.handler;
  2547. if (!handler) {
  2548. return mobx.action(originalFn).apply(null, call.args);
  2549. }
  2550. // skip hooks if asked to
  2551. if (!middleware.includeHooks && Hook[call.name]) {
  2552. return runNextMiddleware(call);
  2553. }
  2554. var nextInvoked = false;
  2555. function next(call2, callback) {
  2556. nextInvoked = true;
  2557. // the result can contain
  2558. // - the non manipulated return value from an action
  2559. // - the non manipulated abort value
  2560. // - one of the above but manipulated through the callback function
  2561. result = runNextMiddleware(call2);
  2562. if (callback) {
  2563. result = callback(result);
  2564. }
  2565. }
  2566. var abortInvoked = false;
  2567. function abort(value) {
  2568. abortInvoked = true;
  2569. // overwrite the result
  2570. // can be manipulated through middlewares earlier in the queue using the callback fn
  2571. result = value;
  2572. }
  2573. handler(call, next, abort);
  2574. if (devMode()) {
  2575. if (!nextInvoked && !abortInvoked) {
  2576. var node2 = getStateTreeNode(call.tree);
  2577. 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.");
  2578. }
  2579. else if (nextInvoked && abortInvoked) {
  2580. var node2 = getStateTreeNode(call.tree);
  2581. 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.");
  2582. }
  2583. }
  2584. return result;
  2585. }
  2586. return runNextMiddleware(baseCall);
  2587. }
  2588. /**
  2589. * Returns the currently executing MST action context, or undefined if none.
  2590. */
  2591. function getRunningActionContext() {
  2592. var current = getCurrentActionContext();
  2593. while (current && current.type !== "action") {
  2594. current = current.parentActionEvent;
  2595. }
  2596. return current;
  2597. }
  2598. function _isActionContextThisOrChildOf(actionContext, sameOrParent, includeSame) {
  2599. var parentId = typeof sameOrParent === "number" ? sameOrParent : sameOrParent.id;
  2600. var current = includeSame
  2601. ? actionContext
  2602. : actionContext.parentActionEvent;
  2603. while (current) {
  2604. if (current.id === parentId) {
  2605. return true;
  2606. }
  2607. current = current.parentActionEvent;
  2608. }
  2609. return false;
  2610. }
  2611. /**
  2612. * Returns if the given action context is a parent of this action context.
  2613. */
  2614. function isActionContextChildOf(actionContext, parent) {
  2615. return _isActionContextThisOrChildOf(actionContext, parent, false);
  2616. }
  2617. /**
  2618. * Returns if the given action context is this or a parent of this action context.
  2619. */
  2620. function isActionContextThisOrChildOf(actionContext, parentOrThis) {
  2621. return _isActionContextThisOrChildOf(actionContext, parentOrThis, true);
  2622. }
  2623. function safeStringify(value) {
  2624. try {
  2625. return JSON.stringify(value);
  2626. }
  2627. catch (e) {
  2628. // istanbul ignore next
  2629. return "<Unserializable: " + e + ">";
  2630. }
  2631. }
  2632. /**
  2633. * @internal
  2634. * @hidden
  2635. */
  2636. function prettyPrintValue(value) {
  2637. return typeof value === "function"
  2638. ? "<function" + (value.name ? " " + value.name : "") + ">"
  2639. : isStateTreeNode(value)
  2640. ? "<" + value + ">"
  2641. : "`" + safeStringify(value) + "`";
  2642. }
  2643. function shortenPrintValue(valueInString) {
  2644. return valueInString.length < 280
  2645. ? valueInString
  2646. : valueInString.substring(0, 272) + "......" + valueInString.substring(valueInString.length - 8);
  2647. }
  2648. function toErrorString(error) {
  2649. var value = error.value;
  2650. var type = error.context[error.context.length - 1].type;
  2651. var fullPath = error.context
  2652. .map(function (_a) {
  2653. var path = _a.path;
  2654. return path;
  2655. })
  2656. .filter(function (path) { return path.length > 0; })
  2657. .join("/");
  2658. var pathPrefix = fullPath.length > 0 ? "at path \"/" + fullPath + "\" " : "";
  2659. var currentTypename = isStateTreeNode(value)
  2660. ? "value of type " + getStateTreeNode(value).type.name + ":"
  2661. : isPrimitive(value)
  2662. ? "value"
  2663. : "snapshot";
  2664. var isSnapshotCompatible = type && isStateTreeNode(value) && type.is(getStateTreeNode(value).snapshot);
  2665. return ("" + pathPrefix + currentTypename + " " + prettyPrintValue(value) + " is not assignable " + (type ? "to type: `" + type.name + "`" : "") +
  2666. (error.message ? " (" + error.message + ")" : "") +
  2667. (type
  2668. ? isPrimitiveType(type) || isPrimitive(value)
  2669. ? "."
  2670. : ", expected an instance of `" + type.name + "` or a snapshot like `" + type.describe() + "` instead." +
  2671. (isSnapshotCompatible
  2672. ? " (Note that a snapshot of the provided value is compatible with the targeted type)"
  2673. : "")
  2674. : "."));
  2675. }
  2676. /**
  2677. * @internal
  2678. * @hidden
  2679. */
  2680. function getContextForPath(context, path, type) {
  2681. return context.concat([{ path: path, type: type }]);
  2682. }
  2683. /**
  2684. * @internal
  2685. * @hidden
  2686. */
  2687. function typeCheckSuccess() {
  2688. return EMPTY_ARRAY;
  2689. }
  2690. /**
  2691. * @internal
  2692. * @hidden
  2693. */
  2694. function typeCheckFailure(context, value, message) {
  2695. return [{ context: context, value: value, message: message }];
  2696. }
  2697. /**
  2698. * @internal
  2699. * @hidden
  2700. */
  2701. function flattenTypeErrors(errors) {
  2702. return errors.reduce(function (a, i) { return a.concat(i); }, []);
  2703. }
  2704. // TODO; doublecheck: typecheck should only needed to be invoked from: type.create and array / map / value.property will change
  2705. /**
  2706. * @internal
  2707. * @hidden
  2708. */
  2709. function typecheckInternal(type, value) {
  2710. // runs typeChecking if it is in dev-mode or through a process.env.ENABLE_TYPE_CHECK flag
  2711. if (isTypeCheckingEnabled()) {
  2712. typecheck(type, value);
  2713. }
  2714. }
  2715. /**
  2716. * Run's the typechecker for the given type on the given value, which can be a snapshot or an instance.
  2717. * Throws if the given value is not according the provided type specification.
  2718. * Use this if you need typechecks even in a production build (by default all automatic runtime type checks will be skipped in production builds)
  2719. *
  2720. * @param type Type to check against.
  2721. * @param value Value to be checked, either a snapshot or an instance.
  2722. */
  2723. function typecheck(type, value) {
  2724. var errors = type.validate(value, [{ path: "", type: type }]);
  2725. if (errors.length > 0) {
  2726. throw fail$1(validationErrorsToString(type, value, errors));
  2727. }
  2728. }
  2729. function validationErrorsToString(type, value, errors) {
  2730. if (errors.length === 0) {
  2731. return undefined;
  2732. }
  2733. return ("Error while converting " + shortenPrintValue(prettyPrintValue(value)) + " to `" + type.name + "`:\n\n " + errors.map(toErrorString).join("\n "));
  2734. }
  2735. var identifierCacheId = 0;
  2736. /**
  2737. * @internal
  2738. * @hidden
  2739. */
  2740. var IdentifierCache = /** @class */ (function () {
  2741. function IdentifierCache() {
  2742. this.cacheId = identifierCacheId++;
  2743. // n.b. in cache all identifiers are normalized to strings
  2744. this.cache = mobx.observable.map();
  2745. // last time the cache (array) for a given time changed
  2746. // n.b. it is not really the time, but just an integer that gets increased after each modification to the array
  2747. this.lastCacheModificationPerId = mobx.observable.map();
  2748. }
  2749. IdentifierCache.prototype.updateLastCacheModificationPerId = function (identifier) {
  2750. var lcm = this.lastCacheModificationPerId.get(identifier);
  2751. // we start at 1 since 0 means no update since cache creation
  2752. this.lastCacheModificationPerId.set(identifier, lcm === undefined ? 1 : lcm + 1);
  2753. };
  2754. IdentifierCache.prototype.getLastCacheModificationPerId = function (identifier) {
  2755. var modificationId = this.lastCacheModificationPerId.get(identifier) || 0;
  2756. return this.cacheId + "-" + modificationId;
  2757. };
  2758. IdentifierCache.prototype.addNodeToCache = function (node, lastCacheUpdate) {
  2759. if (lastCacheUpdate === void 0) { lastCacheUpdate = true; }
  2760. if (node.identifierAttribute) {
  2761. var identifier = node.identifier;
  2762. if (!this.cache.has(identifier)) {
  2763. this.cache.set(identifier, mobx.observable.array([], mobxShallow));
  2764. }
  2765. var set = this.cache.get(identifier);
  2766. if (set.indexOf(node) !== -1)
  2767. throw fail$1("Already registered");
  2768. set.push(node);
  2769. if (lastCacheUpdate) {
  2770. this.updateLastCacheModificationPerId(identifier);
  2771. }
  2772. }
  2773. };
  2774. IdentifierCache.prototype.mergeCache = function (node) {
  2775. var _this = this;
  2776. mobx.values(node.identifierCache.cache).forEach(function (nodes) {
  2777. return nodes.forEach(function (child) {
  2778. _this.addNodeToCache(child);
  2779. });
  2780. });
  2781. };
  2782. IdentifierCache.prototype.notifyDied = function (node) {
  2783. if (node.identifierAttribute) {
  2784. var id = node.identifier;
  2785. var set = this.cache.get(id);
  2786. if (set) {
  2787. set.remove(node);
  2788. // remove empty sets from cache
  2789. if (!set.length) {
  2790. this.cache.delete(id);
  2791. }
  2792. this.updateLastCacheModificationPerId(node.identifier);
  2793. }
  2794. }
  2795. };
  2796. IdentifierCache.prototype.splitCache = function (node) {
  2797. var _this = this;
  2798. var res = new IdentifierCache();
  2799. var basePath = node.path;
  2800. mobx.entries(this.cache).forEach(function (_a) {
  2801. var _b = __read(_a, 2), id = _b[0], nodes = _b[1];
  2802. var modified = false;
  2803. for (var i = nodes.length - 1; i >= 0; i--) {
  2804. if (nodes[i].path.indexOf(basePath) === 0) {
  2805. res.addNodeToCache(nodes[i], false); // no need to update lastUpdated since it is a whole new cache
  2806. nodes.splice(i, 1);
  2807. modified = true;
  2808. }
  2809. }
  2810. if (modified) {
  2811. _this.updateLastCacheModificationPerId(id);
  2812. }
  2813. });
  2814. return res;
  2815. };
  2816. IdentifierCache.prototype.has = function (type, identifier) {
  2817. var set = this.cache.get(identifier);
  2818. if (!set)
  2819. return false;
  2820. return set.some(function (candidate) { return type.isAssignableFrom(candidate.type); });
  2821. };
  2822. IdentifierCache.prototype.resolve = function (type, identifier) {
  2823. var set = this.cache.get(identifier);
  2824. if (!set)
  2825. return null;
  2826. var matches = set.filter(function (candidate) { return type.isAssignableFrom(candidate.type); });
  2827. switch (matches.length) {
  2828. case 0:
  2829. return null;
  2830. case 1:
  2831. return matches[0];
  2832. default:
  2833. throw fail$1("Cannot resolve a reference to type '" + type.name + "' with id: '" + identifier + "' unambigously, there are multiple candidates: " + matches
  2834. .map(function (n) { return n.path; })
  2835. .join(", "));
  2836. }
  2837. };
  2838. return IdentifierCache;
  2839. }());
  2840. /**
  2841. * @internal
  2842. * @hidden
  2843. */
  2844. function createObjectNode(type, parent, subpath, environment, initialValue) {
  2845. var existingNode = getStateTreeNodeSafe(initialValue);
  2846. if (existingNode) {
  2847. if (existingNode.parent) {
  2848. // istanbul ignore next
  2849. 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 + "'");
  2850. }
  2851. if (parent) {
  2852. existingNode.setParent(parent, subpath);
  2853. }
  2854. // else it already has no parent since it is a pre-requisite
  2855. return existingNode;
  2856. }
  2857. // not a node, a snapshot
  2858. return new ObjectNode(type, parent, subpath, environment, initialValue);
  2859. }
  2860. /**
  2861. * @internal
  2862. * @hidden
  2863. */
  2864. function createScalarNode(type, parent, subpath, environment, initialValue) {
  2865. return new ScalarNode(type, parent, subpath, environment, initialValue);
  2866. }
  2867. /**
  2868. * @internal
  2869. * @hidden
  2870. */
  2871. function isNode(value) {
  2872. return value instanceof ScalarNode || value instanceof ObjectNode;
  2873. }
  2874. /**
  2875. * @internal
  2876. * @hidden
  2877. */
  2878. var NodeLifeCycle;
  2879. (function (NodeLifeCycle) {
  2880. NodeLifeCycle[NodeLifeCycle["INITIALIZING"] = 0] = "INITIALIZING";
  2881. NodeLifeCycle[NodeLifeCycle["CREATED"] = 1] = "CREATED";
  2882. NodeLifeCycle[NodeLifeCycle["FINALIZED"] = 2] = "FINALIZED";
  2883. NodeLifeCycle[NodeLifeCycle["DETACHING"] = 3] = "DETACHING";
  2884. NodeLifeCycle[NodeLifeCycle["DEAD"] = 4] = "DEAD"; // no coming back from this one
  2885. })(NodeLifeCycle || (NodeLifeCycle = {}));
  2886. /**
  2887. * Returns true if the given value is a node in a state tree.
  2888. * More precisely, that is, if the value is an instance of a
  2889. * `types.model`, `types.array` or `types.map`.
  2890. *
  2891. * @param value
  2892. * @returns true if the value is a state tree node.
  2893. */
  2894. function isStateTreeNode(value) {
  2895. return !!(value && value.$treenode);
  2896. }
  2897. /**
  2898. * @internal
  2899. * @hidden
  2900. */
  2901. function assertIsStateTreeNode(value, argNumber) {
  2902. assertArg(value, isStateTreeNode, "mobx-state-tree node", argNumber);
  2903. }
  2904. /**
  2905. * @internal
  2906. * @hidden
  2907. */
  2908. function getStateTreeNode(value) {
  2909. if (!isStateTreeNode(value)) {
  2910. // istanbul ignore next
  2911. throw fail$1("Value " + value + " is no MST Node");
  2912. }
  2913. return value.$treenode;
  2914. }
  2915. /**
  2916. * @internal
  2917. * @hidden
  2918. */
  2919. function getStateTreeNodeSafe(value) {
  2920. return (value && value.$treenode) || null;
  2921. }
  2922. /**
  2923. * @internal
  2924. * @hidden
  2925. */
  2926. function toJSON() {
  2927. return getStateTreeNode(this).snapshot;
  2928. }
  2929. var doubleDot = function (_) { return ".."; };
  2930. /**
  2931. * @internal
  2932. * @hidden
  2933. */
  2934. function getRelativePathBetweenNodes(base, target) {
  2935. // PRE condition target is (a child of) base!
  2936. if (base.root !== target.root) {
  2937. throw fail$1("Cannot calculate relative path: objects '" + base + "' and '" + target + "' are not part of the same object tree");
  2938. }
  2939. var baseParts = splitJsonPath(base.path);
  2940. var targetParts = splitJsonPath(target.path);
  2941. var common = 0;
  2942. for (; common < baseParts.length; common++) {
  2943. if (baseParts[common] !== targetParts[common])
  2944. break;
  2945. }
  2946. // TODO: assert that no targetParts paths are "..", "." or ""!
  2947. return (baseParts
  2948. .slice(common)
  2949. .map(doubleDot)
  2950. .join("/") + joinJsonPath(targetParts.slice(common)));
  2951. }
  2952. /**
  2953. * @internal
  2954. * @hidden
  2955. */
  2956. function resolveNodeByPath(base, path, failIfResolveFails) {
  2957. if (failIfResolveFails === void 0) { failIfResolveFails = true; }
  2958. return resolveNodeByPathParts(base, splitJsonPath(path), failIfResolveFails);
  2959. }
  2960. /**
  2961. * @internal
  2962. * @hidden
  2963. */
  2964. function resolveNodeByPathParts(base, pathParts, failIfResolveFails) {
  2965. if (failIfResolveFails === void 0) { failIfResolveFails = true; }
  2966. var current = base;
  2967. for (var i = 0; i < pathParts.length; i++) {
  2968. var part = pathParts[i];
  2969. if (part === "..") {
  2970. current = current.parent;
  2971. if (current)
  2972. continue; // not everything has a parent
  2973. }
  2974. else if (part === ".") {
  2975. continue;
  2976. }
  2977. else if (current) {
  2978. if (current instanceof ScalarNode) {
  2979. // check if the value of a scalar resolves to a state tree node (e.g. references)
  2980. // then we can continue resolving...
  2981. try {
  2982. var value = current.value;
  2983. if (isStateTreeNode(value)) {
  2984. current = getStateTreeNode(value);
  2985. // fall through
  2986. }
  2987. }
  2988. catch (e) {
  2989. if (!failIfResolveFails) {
  2990. return undefined;
  2991. }
  2992. throw e;
  2993. }
  2994. }
  2995. if (current instanceof ObjectNode) {
  2996. var subType = current.getChildType(part);
  2997. if (subType) {
  2998. current = current.getChildNode(part);
  2999. if (current)
  3000. continue;
  3001. }
  3002. }
  3003. }
  3004. if (failIfResolveFails)
  3005. throw fail$1("Could not resolve '" + part + "' in path '" + (joinJsonPath(pathParts.slice(0, i)) ||
  3006. "/") + "' while resolving '" + joinJsonPath(pathParts) + "'");
  3007. else
  3008. return undefined;
  3009. }
  3010. return current;
  3011. }
  3012. /**
  3013. * @internal
  3014. * @hidden
  3015. */
  3016. function convertChildNodesToArray(childNodes) {
  3017. if (!childNodes)
  3018. return EMPTY_ARRAY;
  3019. var keys = Object.keys(childNodes);
  3020. if (!keys.length)
  3021. return EMPTY_ARRAY;
  3022. var result = new Array(keys.length);
  3023. keys.forEach(function (key, index) {
  3024. result[index] = childNodes[key];
  3025. });
  3026. return result;
  3027. }
  3028. // based on: https://github.com/mobxjs/mobx-utils/blob/master/src/async-action.ts
  3029. /*
  3030. All contents of this file are deprecated.
  3031. The term `process` has been replaced with `flow` to avoid conflicts with the
  3032. global `process` object.
  3033. Refer to `flow.ts` for any further changes to this implementation.
  3034. */
  3035. var DEPRECATION_MESSAGE = "See https://github.com/mobxjs/mobx-state-tree/issues/399 for more information. " +
  3036. "Note that the middleware event types starting with `process` now start with `flow`.";
  3037. /**
  3038. * @hidden
  3039. *
  3040. * @deprecated has been renamed to `flow()`.
  3041. * See https://github.com/mobxjs/mobx-state-tree/issues/399 for more information.
  3042. * Note that the middleware event types starting with `process` now start with `flow`.
  3043. *
  3044. * @returns {Promise}
  3045. */
  3046. function process$1(asyncAction) {
  3047. deprecated("process", "`process()` has been renamed to `flow()`. " + DEPRECATION_MESSAGE);
  3048. return flow(asyncAction);
  3049. }
  3050. /**
  3051. * @internal
  3052. * @hidden
  3053. */
  3054. var EMPTY_ARRAY = Object.freeze([]);
  3055. /**
  3056. * @internal
  3057. * @hidden
  3058. */
  3059. var EMPTY_OBJECT = Object.freeze({});
  3060. /**
  3061. * @internal
  3062. * @hidden
  3063. */
  3064. var mobxShallow = typeof mobx.$mobx === "string" ? { deep: false } : { deep: false, proxy: false };
  3065. Object.freeze(mobxShallow);
  3066. /**
  3067. * @internal
  3068. * @hidden
  3069. */
  3070. function fail$1(message) {
  3071. if (message === void 0) { message = "Illegal state"; }
  3072. return new Error("[mobx-state-tree] " + message);
  3073. }
  3074. /**
  3075. * @internal
  3076. * @hidden
  3077. */
  3078. function identity(_) {
  3079. return _;
  3080. }
  3081. /**
  3082. * pollyfill (for IE) suggested in MDN:
  3083. * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger
  3084. * @internal
  3085. * @hidden
  3086. */
  3087. var isInteger = Number.isInteger ||
  3088. function (value) {
  3089. return typeof value === "number" && isFinite(value) && Math.floor(value) === value;
  3090. };
  3091. /**
  3092. * @internal
  3093. * @hidden
  3094. */
  3095. function isArray(val) {
  3096. return Array.isArray(val) || mobx.isObservableArray(val);
  3097. }
  3098. /**
  3099. * @internal
  3100. * @hidden
  3101. */
  3102. function asArray(val) {
  3103. if (!val)
  3104. return EMPTY_ARRAY;
  3105. if (isArray(val))
  3106. return val;
  3107. return [val];
  3108. }
  3109. /**
  3110. * @internal
  3111. * @hidden
  3112. */
  3113. function extend(a) {
  3114. var b = [];
  3115. for (var _i = 1; _i < arguments.length; _i++) {
  3116. b[_i - 1] = arguments[_i];
  3117. }
  3118. for (var i = 0; i < b.length; i++) {
  3119. var current = b[i];
  3120. for (var key in current)
  3121. a[key] = current[key];
  3122. }
  3123. return a;
  3124. }
  3125. /**
  3126. * @internal
  3127. * @hidden
  3128. */
  3129. function isPlainObject(value) {
  3130. if (value === null || typeof value !== "object")
  3131. return false;
  3132. var proto = Object.getPrototypeOf(value);
  3133. return proto === Object.prototype || proto === null;
  3134. }
  3135. /**
  3136. * @internal
  3137. * @hidden
  3138. */
  3139. function isMutable(value) {
  3140. return (value !== null &&
  3141. typeof value === "object" &&
  3142. !(value instanceof Date) &&
  3143. !(value instanceof RegExp));
  3144. }
  3145. /**
  3146. * @internal
  3147. * @hidden
  3148. */
  3149. function isPrimitive(value, includeDate) {
  3150. if (includeDate === void 0) { includeDate = true; }
  3151. if (value === null || value === undefined)
  3152. return true;
  3153. if (typeof value === "string" ||
  3154. typeof value === "number" ||
  3155. typeof value === "boolean" ||
  3156. (includeDate && value instanceof Date))
  3157. return true;
  3158. return false;
  3159. }
  3160. /**
  3161. * @internal
  3162. * @hidden
  3163. * Freeze a value and return it (if not in production)
  3164. */
  3165. function freeze(value) {
  3166. if (!devMode())
  3167. return value;
  3168. return isPrimitive(value) || mobx.isObservableArray(value) ? value : Object.freeze(value);
  3169. }
  3170. /**
  3171. * @internal
  3172. * @hidden
  3173. * Recursively freeze a value (if not in production)
  3174. */
  3175. function deepFreeze(value) {
  3176. if (!devMode())
  3177. return value;
  3178. freeze(value);
  3179. if (isPlainObject(value)) {
  3180. Object.keys(value).forEach(function (propKey) {
  3181. if (!isPrimitive(value[propKey]) &&
  3182. !Object.isFrozen(value[propKey])) {
  3183. deepFreeze(value[propKey]);
  3184. }
  3185. });
  3186. }
  3187. return value;
  3188. }
  3189. /**
  3190. * @internal
  3191. * @hidden
  3192. */
  3193. function isSerializable(value) {
  3194. return typeof value !== "function";
  3195. }
  3196. /**
  3197. * @internal
  3198. * @hidden
  3199. */
  3200. function addHiddenFinalProp(object, propName, value) {
  3201. Object.defineProperty(object, propName, {
  3202. enumerable: false,
  3203. writable: false,
  3204. configurable: true,
  3205. value: value
  3206. });
  3207. }
  3208. /**
  3209. * @internal
  3210. * @hidden
  3211. */
  3212. function addHiddenWritableProp(object, propName, value) {
  3213. Object.defineProperty(object, propName, {
  3214. enumerable: false,
  3215. writable: true,
  3216. configurable: true,
  3217. value: value
  3218. });
  3219. }
  3220. /**
  3221. * @internal
  3222. * @hidden
  3223. */
  3224. var EventHandler = /** @class */ (function () {
  3225. function EventHandler() {
  3226. this.handlers = [];
  3227. }
  3228. Object.defineProperty(EventHandler.prototype, "hasSubscribers", {
  3229. get: function () {
  3230. return this.handlers.length > 0;
  3231. },
  3232. enumerable: true,
  3233. configurable: true
  3234. });
  3235. EventHandler.prototype.register = function (fn, atTheBeginning) {
  3236. var _this = this;
  3237. if (atTheBeginning === void 0) { atTheBeginning = false; }
  3238. if (atTheBeginning) {
  3239. this.handlers.unshift(fn);
  3240. }
  3241. else {
  3242. this.handlers.push(fn);
  3243. }
  3244. return function () {
  3245. _this.unregister(fn);
  3246. };
  3247. };
  3248. EventHandler.prototype.has = function (fn) {
  3249. return this.handlers.indexOf(fn) >= 0;
  3250. };
  3251. EventHandler.prototype.unregister = function (fn) {
  3252. var index = this.handlers.indexOf(fn);
  3253. if (index >= 0) {
  3254. this.handlers.splice(index, 1);
  3255. }
  3256. };
  3257. EventHandler.prototype.clear = function () {
  3258. this.handlers.length = 0;
  3259. };
  3260. EventHandler.prototype.emit = function () {
  3261. var args = [];
  3262. for (var _i = 0; _i < arguments.length; _i++) {
  3263. args[_i] = arguments[_i];
  3264. }
  3265. // make a copy just in case it changes
  3266. var handlers = this.handlers.slice();
  3267. handlers.forEach(function (f) { return f.apply(void 0, __spread(args)); });
  3268. };
  3269. return EventHandler;
  3270. }());
  3271. /**
  3272. * @internal
  3273. * @hidden
  3274. */
  3275. var EventHandlers = /** @class */ (function () {
  3276. function EventHandlers() {
  3277. }
  3278. EventHandlers.prototype.hasSubscribers = function (event) {
  3279. var handler = this.eventHandlers && this.eventHandlers[event];
  3280. return !!handler && handler.hasSubscribers;
  3281. };
  3282. EventHandlers.prototype.register = function (event, fn, atTheBeginning) {
  3283. if (atTheBeginning === void 0) { atTheBeginning = false; }
  3284. if (!this.eventHandlers) {
  3285. this.eventHandlers = {};
  3286. }
  3287. var handler = this.eventHandlers[event];
  3288. if (!handler) {
  3289. handler = this.eventHandlers[event] = new EventHandler();
  3290. }
  3291. return handler.register(fn, atTheBeginning);
  3292. };
  3293. EventHandlers.prototype.has = function (event, fn) {
  3294. var handler = this.eventHandlers && this.eventHandlers[event];
  3295. return !!handler && handler.has(fn);
  3296. };
  3297. EventHandlers.prototype.unregister = function (event, fn) {
  3298. var handler = this.eventHandlers && this.eventHandlers[event];
  3299. if (handler) {
  3300. handler.unregister(fn);
  3301. }
  3302. };
  3303. EventHandlers.prototype.clear = function (event) {
  3304. if (this.eventHandlers) {
  3305. delete this.eventHandlers[event];
  3306. }
  3307. };
  3308. EventHandlers.prototype.clearAll = function () {
  3309. this.eventHandlers = undefined;
  3310. };
  3311. EventHandlers.prototype.emit = function (event) {
  3312. var _a;
  3313. var args = [];
  3314. for (var _i = 1; _i < arguments.length; _i++) {
  3315. args[_i - 1] = arguments[_i];
  3316. }
  3317. var handler = this.eventHandlers && this.eventHandlers[event];
  3318. if (handler) {
  3319. (_a = handler).emit.apply(_a, __spread(args));
  3320. }
  3321. };
  3322. return EventHandlers;
  3323. }());
  3324. /**
  3325. * @internal
  3326. * @hidden
  3327. */
  3328. function argsToArray(args) {
  3329. var res = new Array(args.length);
  3330. for (var i = 0; i < args.length; i++)
  3331. res[i] = args[i];
  3332. return res;
  3333. }
  3334. /**
  3335. * @internal
  3336. * @hidden
  3337. */
  3338. function invalidateComputed(target, propName) {
  3339. var atom = mobx.getAtom(target, propName);
  3340. atom.trackAndCompute();
  3341. }
  3342. /**
  3343. * @internal
  3344. * @hidden
  3345. */
  3346. function stringStartsWith(str, beginning) {
  3347. return str.indexOf(beginning) === 0;
  3348. }
  3349. /**
  3350. * @internal
  3351. * @hidden
  3352. */
  3353. var deprecated = function (id, message) {
  3354. // skip if running production
  3355. if (!devMode())
  3356. return;
  3357. // warn if hasn't been warned before
  3358. if (deprecated.ids && !deprecated.ids.hasOwnProperty(id)) {
  3359. warnError("Deprecation warning: " + message);
  3360. }
  3361. // mark as warned to avoid duplicate warn message
  3362. if (deprecated.ids)
  3363. deprecated.ids[id] = true;
  3364. };
  3365. deprecated.ids = {};
  3366. /**
  3367. * @internal
  3368. * @hidden
  3369. */
  3370. function warnError(msg) {
  3371. console.warn(new Error("[mobx-state-tree] " + msg));
  3372. }
  3373. /**
  3374. * @internal
  3375. * @hidden
  3376. */
  3377. function isTypeCheckingEnabled() {
  3378. return (devMode() ||
  3379. (typeof process !== "undefined" && process.env && process.env.ENABLE_TYPE_CHECK === "true"));
  3380. }
  3381. /**
  3382. * @internal
  3383. * @hidden
  3384. */
  3385. function devMode() {
  3386. return process.env.NODE_ENV !== "production";
  3387. }
  3388. /**
  3389. * @internal
  3390. * @hidden
  3391. */
  3392. function assertArg(value, fn, typeName, argNumber) {
  3393. if (devMode()) {
  3394. if (!fn(value)) {
  3395. // istanbul ignore next
  3396. throw fail$1("expected " + typeName + " as argument " + asArray(argNumber).join(" or ") + ", got " + value + " instead");
  3397. }
  3398. }
  3399. }
  3400. /**
  3401. * @internal
  3402. * @hidden
  3403. */
  3404. function assertIsFunction(value, argNumber) {
  3405. assertArg(value, function (fn) { return typeof fn === "function"; }, "function", argNumber);
  3406. }
  3407. /**
  3408. * @internal
  3409. * @hidden
  3410. */
  3411. function assertIsNumber(value, argNumber, min, max) {
  3412. assertArg(value, function (n) { return typeof n === "number"; }, "number", argNumber);
  3413. if (min !== undefined) {
  3414. assertArg(value, function (n) { return n >= min; }, "number greater than " + min, argNumber);
  3415. }
  3416. if (max !== undefined) {
  3417. assertArg(value, function (n) { return n <= max; }, "number lesser than " + max, argNumber);
  3418. }
  3419. }
  3420. /**
  3421. * @internal
  3422. * @hidden
  3423. */
  3424. function assertIsString(value, argNumber, canBeEmpty) {
  3425. if (canBeEmpty === void 0) { canBeEmpty = true; }
  3426. assertArg(value, function (s) { return typeof s === "string"; }, "string", argNumber);
  3427. if (!canBeEmpty) {
  3428. assertArg(value, function (s) { return s !== ""; }, "not empty string", argNumber);
  3429. }
  3430. }
  3431. /**
  3432. * See [asynchronous actions](https://github.com/mobxjs/mobx-state-tree/blob/master/docs/async-actions.md).
  3433. *
  3434. * @returns The flow as a promise.
  3435. */
  3436. function flow(generator) {
  3437. return createFlowSpawner(generator.name, generator);
  3438. }
  3439. /**
  3440. * @deprecated Not needed since TS3.6.
  3441. * Used for TypeScript to make flows that return a promise return the actual promise result.
  3442. *
  3443. * @param val
  3444. * @returns
  3445. */
  3446. function castFlowReturn(val) {
  3447. return val;
  3448. }
  3449. /**
  3450. * @internal
  3451. * @hidden
  3452. */
  3453. function createFlowSpawner(name, generator) {
  3454. var spawner = function flowSpawner() {
  3455. // Implementation based on https://github.com/tj/co/blob/master/index.js
  3456. var runId = getNextActionId();
  3457. var parentContext = getCurrentActionContext();
  3458. if (!parentContext) {
  3459. throw fail$1("a mst flow must always have a parent context");
  3460. }
  3461. var parentActionContext = getParentActionContext(parentContext);
  3462. if (!parentActionContext) {
  3463. throw fail$1("a mst flow must always have a parent action context");
  3464. }
  3465. var contextBase = {
  3466. name: name,
  3467. id: runId,
  3468. tree: parentContext.tree,
  3469. context: parentContext.context,
  3470. parentId: parentContext.id,
  3471. allParentIds: __spread(parentContext.allParentIds, [parentContext.id]),
  3472. rootId: parentContext.rootId,
  3473. parentEvent: parentContext,
  3474. parentActionEvent: parentActionContext
  3475. };
  3476. var args = arguments;
  3477. function wrap(fn, type, arg) {
  3478. fn.$mst_middleware = spawner.$mst_middleware; // pick up any middleware attached to the flow
  3479. runWithActionContext(__assign(__assign({}, contextBase), { type: type, args: [arg] }), fn);
  3480. }
  3481. return new Promise(function (resolve, reject) {
  3482. var gen;
  3483. var init = function asyncActionInit() {
  3484. gen = generator.apply(null, arguments);
  3485. onFulfilled(undefined); // kick off the flow
  3486. };
  3487. init.$mst_middleware = spawner.$mst_middleware;
  3488. runWithActionContext(__assign(__assign({}, contextBase), { type: "flow_spawn", args: argsToArray(args) }), init);
  3489. function onFulfilled(res) {
  3490. var ret;
  3491. try {
  3492. // prettier-ignore
  3493. wrap(function (r) { ret = gen.next(r); }, "flow_resume", res);
  3494. }
  3495. catch (e) {
  3496. // prettier-ignore
  3497. setImmediate(function () {
  3498. wrap(function (r) { reject(e); }, "flow_throw", e);
  3499. });
  3500. return;
  3501. }
  3502. next(ret);
  3503. return;
  3504. }
  3505. function onRejected(err) {
  3506. var ret;
  3507. try {
  3508. // prettier-ignore
  3509. wrap(function (r) { ret = gen.throw(r); }, "flow_resume_error", err); // or yieldError?
  3510. }
  3511. catch (e) {
  3512. // prettier-ignore
  3513. setImmediate(function () {
  3514. wrap(function (r) { reject(e); }, "flow_throw", e);
  3515. });
  3516. return;
  3517. }
  3518. next(ret);
  3519. }
  3520. function next(ret) {
  3521. if (ret.done) {
  3522. // prettier-ignore
  3523. setImmediate(function () {
  3524. wrap(function (r) { resolve(r); }, "flow_return", ret.value);
  3525. });
  3526. return;
  3527. }
  3528. // TODO: support more type of values? See https://github.com/tj/co/blob/249bbdc72da24ae44076afd716349d2089b31c4c/index.js#L100
  3529. if (!ret.value || typeof ret.value.then !== "function") {
  3530. // istanbul ignore next
  3531. throw fail$1("Only promises can be yielded to `async`, got: " + ret);
  3532. }
  3533. return ret.value.then(onFulfilled, onRejected);
  3534. }
  3535. });
  3536. };
  3537. return spawner;
  3538. }
  3539. /**
  3540. * @internal
  3541. * @hidden
  3542. */
  3543. function splitPatch(patch) {
  3544. if (!("oldValue" in patch))
  3545. throw fail$1("Patches without `oldValue` field cannot be inversed");
  3546. return [stripPatch(patch), invertPatch(patch)];
  3547. }
  3548. /**
  3549. * @internal
  3550. * @hidden
  3551. */
  3552. function stripPatch(patch) {
  3553. // strips `oldvalue` information from the patch, so that it becomes a patch conform the json-patch spec
  3554. // this removes the ability to undo the patch
  3555. switch (patch.op) {
  3556. case "add":
  3557. return { op: "add", path: patch.path, value: patch.value };
  3558. case "remove":
  3559. return { op: "remove", path: patch.path };
  3560. case "replace":
  3561. return { op: "replace", path: patch.path, value: patch.value };
  3562. }
  3563. }
  3564. function invertPatch(patch) {
  3565. switch (patch.op) {
  3566. case "add":
  3567. return {
  3568. op: "remove",
  3569. path: patch.path
  3570. };
  3571. case "remove":
  3572. return {
  3573. op: "add",
  3574. path: patch.path,
  3575. value: patch.oldValue
  3576. };
  3577. case "replace":
  3578. return {
  3579. op: "replace",
  3580. path: patch.path,
  3581. value: patch.oldValue
  3582. };
  3583. }
  3584. }
  3585. /**
  3586. * Simple simple check to check it is a number.
  3587. */
  3588. function isNumber(x) {
  3589. return typeof x === "number";
  3590. }
  3591. /**
  3592. * Escape slashes and backslashes.
  3593. *
  3594. * http://tools.ietf.org/html/rfc6901
  3595. */
  3596. function escapeJsonPath(path) {
  3597. if (isNumber(path) === true) {
  3598. return "" + path;
  3599. }
  3600. if (path.indexOf("/") === -1 && path.indexOf("~") === -1)
  3601. return path;
  3602. return path.replace(/~/g, "~0").replace(/\//g, "~1");
  3603. }
  3604. /**
  3605. * Unescape slashes and backslashes.
  3606. */
  3607. function unescapeJsonPath(path) {
  3608. return path.replace(/~1/g, "/").replace(/~0/g, "~");
  3609. }
  3610. /**
  3611. * Generates a json-path compliant json path from path parts.
  3612. *
  3613. * @param path
  3614. * @returns
  3615. */
  3616. function joinJsonPath(path) {
  3617. // `/` refers to property with an empty name, while `` refers to root itself!
  3618. if (path.length === 0)
  3619. return "";
  3620. var getPathStr = function (p) { return p.map(escapeJsonPath).join("/"); };
  3621. if (path[0] === "." || path[0] === "..") {
  3622. // relative
  3623. return getPathStr(path);
  3624. }
  3625. else {
  3626. // absolute
  3627. return "/" + getPathStr(path);
  3628. }
  3629. }
  3630. /**
  3631. * Splits and decodes a json path into several parts.
  3632. *
  3633. * @param path
  3634. * @returns
  3635. */
  3636. function splitJsonPath(path) {
  3637. // `/` refers to property with an empty name, while `` refers to root itself!
  3638. var parts = path.split("/").map(unescapeJsonPath);
  3639. var valid = path === "" ||
  3640. path === "." ||
  3641. path === ".." ||
  3642. stringStartsWith(path, "/") ||
  3643. stringStartsWith(path, "./") ||
  3644. stringStartsWith(path, "../");
  3645. if (!valid) {
  3646. throw fail$1("a json path must be either rooted, empty or relative, but got '" + path + "'");
  3647. }
  3648. // '/a/b/c' -> ["a", "b", "c"]
  3649. // '../../b/c' -> ["..", "..", "b", "c"]
  3650. // '' -> []
  3651. // '/' -> ['']
  3652. // './a' -> [".", "a"]
  3653. // /./a' -> [".", "a"] equivalent to './a'
  3654. if (parts[0] === "") {
  3655. parts.shift();
  3656. }
  3657. return parts;
  3658. }
  3659. var SnapshotProcessor = /** @class */ (function (_super) {
  3660. __extends(SnapshotProcessor, _super);
  3661. function SnapshotProcessor(_subtype, _processors, name) {
  3662. var _this = _super.call(this, name || _subtype.name) || this;
  3663. _this._subtype = _subtype;
  3664. _this._processors = _processors;
  3665. return _this;
  3666. }
  3667. Object.defineProperty(SnapshotProcessor.prototype, "flags", {
  3668. get: function () {
  3669. return this._subtype.flags | TypeFlags.SnapshotProcessor;
  3670. },
  3671. enumerable: true,
  3672. configurable: true
  3673. });
  3674. SnapshotProcessor.prototype.describe = function () {
  3675. return "snapshotProcessor(" + this._subtype.describe() + ")";
  3676. };
  3677. SnapshotProcessor.prototype.preProcessSnapshot = function (sn) {
  3678. if (this._processors.preProcessor) {
  3679. return this._processors.preProcessor.call(null, sn);
  3680. }
  3681. return sn;
  3682. };
  3683. SnapshotProcessor.prototype.postProcessSnapshot = function (sn) {
  3684. if (this._processors.postProcessor) {
  3685. return this._processors.postProcessor.call(null, sn);
  3686. }
  3687. return sn;
  3688. };
  3689. SnapshotProcessor.prototype._fixNode = function (node) {
  3690. var _this = this;
  3691. // the node has to use these methods rather than the original type ones
  3692. proxyNodeTypeMethods(node.type, this, "isAssignableFrom", "create");
  3693. var oldGetSnapshot = node.getSnapshot;
  3694. node.getSnapshot = function () {
  3695. return _this.postProcessSnapshot(oldGetSnapshot.call(node));
  3696. };
  3697. };
  3698. SnapshotProcessor.prototype.instantiate = function (parent, subpath, environment, initialValue) {
  3699. var processedInitialValue = isStateTreeNode(initialValue)
  3700. ? initialValue
  3701. : this.preProcessSnapshot(initialValue);
  3702. var node = this._subtype.instantiate(parent, subpath, environment, processedInitialValue);
  3703. this._fixNode(node);
  3704. return node;
  3705. };
  3706. SnapshotProcessor.prototype.reconcile = function (current, newValue, parent, subpath) {
  3707. var node = this._subtype.reconcile(current, isStateTreeNode(newValue) ? newValue : this.preProcessSnapshot(newValue), parent, subpath);
  3708. if (node !== current) {
  3709. this._fixNode(node);
  3710. }
  3711. return node;
  3712. };
  3713. SnapshotProcessor.prototype.getSnapshot = function (node, applyPostProcess) {
  3714. if (applyPostProcess === void 0) { applyPostProcess = true; }
  3715. var sn = this._subtype.getSnapshot(node);
  3716. return applyPostProcess ? this.postProcessSnapshot(sn) : sn;
  3717. };
  3718. SnapshotProcessor.prototype.isValidSnapshot = function (value, context) {
  3719. var processedSn = this.preProcessSnapshot(value);
  3720. return this._subtype.validate(processedSn, context);
  3721. };
  3722. SnapshotProcessor.prototype.getSubTypes = function () {
  3723. return this._subtype;
  3724. };
  3725. SnapshotProcessor.prototype.is = function (thing) {
  3726. return (this._subtype.validate(isType(thing) ? this._subtype : this.preProcessSnapshot(thing), [
  3727. { path: "", type: this._subtype }
  3728. ]).length === 0);
  3729. };
  3730. return SnapshotProcessor;
  3731. }(BaseType));
  3732. function proxyNodeTypeMethods(nodeType, snapshotProcessorType) {
  3733. var e_1, _a;
  3734. var methods = [];
  3735. for (var _i = 2; _i < arguments.length; _i++) {
  3736. methods[_i - 2] = arguments[_i];
  3737. }
  3738. try {
  3739. for (var methods_1 = __values(methods), methods_1_1 = methods_1.next(); !methods_1_1.done; methods_1_1 = methods_1.next()) {
  3740. var method = methods_1_1.value;
  3741. nodeType[method] = snapshotProcessorType[method].bind(snapshotProcessorType);
  3742. }
  3743. }
  3744. catch (e_1_1) { e_1 = { error: e_1_1 }; }
  3745. finally {
  3746. try {
  3747. if (methods_1_1 && !methods_1_1.done && (_a = methods_1.return)) _a.call(methods_1);
  3748. }
  3749. finally { if (e_1) throw e_1.error; }
  3750. }
  3751. }
  3752. /**
  3753. * `types.snapshotProcessor` - Runs a pre/post snapshot processor before/after serializing a given type.
  3754. *
  3755. * Example:
  3756. * ```ts
  3757. * const Todo1 = types.model({ text: types.string })
  3758. * // in the backend the text type must be null when empty
  3759. * interface BackendTodo {
  3760. * text: string | null
  3761. * }
  3762. * const Todo2 = types.snapshotProcessor(Todo1, {
  3763. * // from snapshot to instance
  3764. * preProcessor(sn: BackendTodo) {
  3765. * return {
  3766. * text: sn.text || "";
  3767. * }
  3768. * },
  3769. * // from instance to snapshot
  3770. * postProcessor(sn): BackendTodo {
  3771. * return {
  3772. * text: !sn.text ? null : sn.text
  3773. * }
  3774. * }
  3775. * })
  3776. * ```
  3777. *
  3778. * @param type Type to run the processors over.
  3779. * @param processors Processors to run.
  3780. * @param name Type name, or undefined to inherit the inner type one.
  3781. * @returns
  3782. */
  3783. function snapshotProcessor(type, processors, name) {
  3784. assertIsType(type, 1);
  3785. if (devMode()) {
  3786. if (processors.postProcessor && typeof processors.postProcessor !== "function") {
  3787. // istanbul ignore next
  3788. throw fail("postSnapshotProcessor must be a function");
  3789. }
  3790. if (processors.preProcessor && typeof processors.preProcessor !== "function") {
  3791. // istanbul ignore next
  3792. throw fail("preSnapshotProcessor must be a function");
  3793. }
  3794. }
  3795. return new SnapshotProcessor(type, processors, name);
  3796. }
  3797. var needsIdentifierError = "Map.put can only be used to store complex values that have an identifier type attribute";
  3798. function tryCollectModelTypes(type, modelTypes) {
  3799. var e_1, _a;
  3800. var subtypes = type.getSubTypes();
  3801. if (subtypes === cannotDetermineSubtype) {
  3802. return false;
  3803. }
  3804. if (subtypes) {
  3805. var subtypesArray = asArray(subtypes);
  3806. try {
  3807. for (var subtypesArray_1 = __values(subtypesArray), subtypesArray_1_1 = subtypesArray_1.next(); !subtypesArray_1_1.done; subtypesArray_1_1 = subtypesArray_1.next()) {
  3808. var subtype = subtypesArray_1_1.value;
  3809. if (!tryCollectModelTypes(subtype, modelTypes))
  3810. return false;
  3811. }
  3812. }
  3813. catch (e_1_1) { e_1 = { error: e_1_1 }; }
  3814. finally {
  3815. try {
  3816. if (subtypesArray_1_1 && !subtypesArray_1_1.done && (_a = subtypesArray_1.return)) _a.call(subtypesArray_1);
  3817. }
  3818. finally { if (e_1) throw e_1.error; }
  3819. }
  3820. }
  3821. if (type instanceof ModelType) {
  3822. modelTypes.push(type);
  3823. }
  3824. return true;
  3825. }
  3826. /**
  3827. * @internal
  3828. * @hidden
  3829. */
  3830. var MapIdentifierMode;
  3831. (function (MapIdentifierMode) {
  3832. MapIdentifierMode[MapIdentifierMode["UNKNOWN"] = 0] = "UNKNOWN";
  3833. MapIdentifierMode[MapIdentifierMode["YES"] = 1] = "YES";
  3834. MapIdentifierMode[MapIdentifierMode["NO"] = 2] = "NO";
  3835. })(MapIdentifierMode || (MapIdentifierMode = {}));
  3836. var MSTMap = /** @class */ (function (_super) {
  3837. __extends(MSTMap, _super);
  3838. function MSTMap(initialData) {
  3839. return _super.call(this, initialData, mobx.observable.ref.enhancer) || this;
  3840. }
  3841. MSTMap.prototype.get = function (key) {
  3842. // maybe this is over-enthousiastic? normalize numeric keys to strings
  3843. return _super.prototype.get.call(this, "" + key);
  3844. };
  3845. MSTMap.prototype.has = function (key) {
  3846. return _super.prototype.has.call(this, "" + key);
  3847. };
  3848. MSTMap.prototype.delete = function (key) {
  3849. return _super.prototype.delete.call(this, "" + key);
  3850. };
  3851. MSTMap.prototype.set = function (key, value) {
  3852. return _super.prototype.set.call(this, "" + key, value);
  3853. };
  3854. MSTMap.prototype.put = function (value) {
  3855. if (!value)
  3856. throw fail$1("Map.put cannot be used to set empty values");
  3857. if (isStateTreeNode(value)) {
  3858. var node = getStateTreeNode(value);
  3859. if (devMode()) {
  3860. if (!node.identifierAttribute) {
  3861. throw fail$1(needsIdentifierError);
  3862. }
  3863. }
  3864. if (node.identifier === null) {
  3865. throw fail$1(needsIdentifierError);
  3866. }
  3867. this.set(node.identifier, value);
  3868. return value;
  3869. }
  3870. else if (!isMutable(value)) {
  3871. throw fail$1("Map.put can only be used to store complex values");
  3872. }
  3873. else {
  3874. var mapNode = getStateTreeNode(this);
  3875. var mapType = mapNode.type;
  3876. if (mapType.identifierMode !== MapIdentifierMode.YES) {
  3877. throw fail$1(needsIdentifierError);
  3878. }
  3879. var idAttr = mapType.mapIdentifierAttribute;
  3880. var id = value[idAttr];
  3881. if (!isValidIdentifier(id)) {
  3882. // try again but this time after creating a node for the value
  3883. // since it might be an optional identifier
  3884. var newNode = this.put(mapType.getChildType().create(value, mapNode.environment));
  3885. return this.put(getSnapshot(newNode));
  3886. }
  3887. var key = normalizeIdentifier(id);
  3888. this.set(key, value);
  3889. return this.get(key);
  3890. }
  3891. };
  3892. return MSTMap;
  3893. }(mobx.ObservableMap));
  3894. /**
  3895. * @internal
  3896. * @hidden
  3897. */
  3898. var MapType = /** @class */ (function (_super) {
  3899. __extends(MapType, _super);
  3900. function MapType(name, _subType, hookInitializers) {
  3901. if (hookInitializers === void 0) { hookInitializers = []; }
  3902. var _this = _super.call(this, name) || this;
  3903. _this._subType = _subType;
  3904. _this.identifierMode = MapIdentifierMode.UNKNOWN;
  3905. _this.mapIdentifierAttribute = undefined;
  3906. _this.flags = TypeFlags.Map;
  3907. _this.hookInitializers = [];
  3908. _this._determineIdentifierMode();
  3909. _this.hookInitializers = hookInitializers;
  3910. return _this;
  3911. }
  3912. MapType.prototype.hooks = function (hooks) {
  3913. var hookInitializers = this.hookInitializers.length > 0 ? this.hookInitializers.concat(hooks) : [hooks];
  3914. return new MapType(this.name, this._subType, hookInitializers);
  3915. };
  3916. MapType.prototype.instantiate = function (parent, subpath, environment, initialValue) {
  3917. this._determineIdentifierMode();
  3918. return createObjectNode(this, parent, subpath, environment, initialValue);
  3919. };
  3920. MapType.prototype._determineIdentifierMode = function () {
  3921. if (this.identifierMode !== MapIdentifierMode.UNKNOWN) {
  3922. return;
  3923. }
  3924. var modelTypes = [];
  3925. if (tryCollectModelTypes(this._subType, modelTypes)) {
  3926. var identifierAttribute_1 = undefined;
  3927. modelTypes.forEach(function (type) {
  3928. if (type.identifierAttribute) {
  3929. if (identifierAttribute_1 && identifierAttribute_1 !== type.identifierAttribute) {
  3930. 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");
  3931. }
  3932. identifierAttribute_1 = type.identifierAttribute;
  3933. }
  3934. });
  3935. if (identifierAttribute_1) {
  3936. this.identifierMode = MapIdentifierMode.YES;
  3937. this.mapIdentifierAttribute = identifierAttribute_1;
  3938. }
  3939. else {
  3940. this.identifierMode = MapIdentifierMode.NO;
  3941. }
  3942. }
  3943. };
  3944. MapType.prototype.initializeChildNodes = function (objNode, initialSnapshot) {
  3945. if (initialSnapshot === void 0) { initialSnapshot = {}; }
  3946. var subType = objNode.type._subType;
  3947. var result = {};
  3948. Object.keys(initialSnapshot).forEach(function (name) {
  3949. result[name] = subType.instantiate(objNode, name, undefined, initialSnapshot[name]);
  3950. });
  3951. return result;
  3952. };
  3953. MapType.prototype.createNewInstance = function (childNodes) {
  3954. return new MSTMap(childNodes);
  3955. };
  3956. MapType.prototype.finalizeNewInstance = function (node, instance) {
  3957. mobx._interceptReads(instance, node.unbox);
  3958. var type = node.type;
  3959. type.hookInitializers.forEach(function (initializer) {
  3960. var hooks = initializer(instance);
  3961. Object.keys(hooks).forEach(function (name) {
  3962. var hook = hooks[name];
  3963. var actionInvoker = createActionInvoker(instance, name, hook);
  3964. (!devMode() ? addHiddenFinalProp : addHiddenWritableProp)(instance, name, actionInvoker);
  3965. });
  3966. });
  3967. mobx.intercept(instance, this.willChange);
  3968. mobx.observe(instance, this.didChange);
  3969. };
  3970. MapType.prototype.describe = function () {
  3971. return "Map<string, " + this._subType.describe() + ">";
  3972. };
  3973. MapType.prototype.getChildren = function (node) {
  3974. // return (node.storedValue as ObservableMap<any>).values()
  3975. return mobx.values(node.storedValue);
  3976. };
  3977. MapType.prototype.getChildNode = function (node, key) {
  3978. var childNode = node.storedValue.get("" + key);
  3979. if (!childNode)
  3980. throw fail$1("Not a child " + key);
  3981. return childNode;
  3982. };
  3983. MapType.prototype.willChange = function (change) {
  3984. var node = getStateTreeNode(change.object);
  3985. var key = change.name;
  3986. node.assertWritable({ subpath: key });
  3987. var mapType = node.type;
  3988. var subType = mapType._subType;
  3989. switch (change.type) {
  3990. case "update":
  3991. {
  3992. var newValue = change.newValue;
  3993. var oldValue = change.object.get(key);
  3994. if (newValue === oldValue)
  3995. return null;
  3996. typecheckInternal(subType, newValue);
  3997. change.newValue = subType.reconcile(node.getChildNode(key), change.newValue, node, key);
  3998. mapType.processIdentifier(key, change.newValue);
  3999. }
  4000. break;
  4001. case "add":
  4002. {
  4003. typecheckInternal(subType, change.newValue);
  4004. change.newValue = subType.instantiate(node, key, undefined, change.newValue);
  4005. mapType.processIdentifier(key, change.newValue);
  4006. }
  4007. break;
  4008. }
  4009. return change;
  4010. };
  4011. MapType.prototype.processIdentifier = function (expected, node) {
  4012. if (this.identifierMode === MapIdentifierMode.YES && node instanceof ObjectNode) {
  4013. var identifier = node.identifier;
  4014. if (identifier !== expected)
  4015. 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 + "'");
  4016. }
  4017. };
  4018. MapType.prototype.getSnapshot = function (node) {
  4019. var res = {};
  4020. node.getChildren().forEach(function (childNode) {
  4021. res[childNode.subpath] = childNode.snapshot;
  4022. });
  4023. return res;
  4024. };
  4025. MapType.prototype.processInitialSnapshot = function (childNodes) {
  4026. var processed = {};
  4027. Object.keys(childNodes).forEach(function (key) {
  4028. processed[key] = childNodes[key].getSnapshot();
  4029. });
  4030. return processed;
  4031. };
  4032. MapType.prototype.didChange = function (change) {
  4033. var node = getStateTreeNode(change.object);
  4034. switch (change.type) {
  4035. case "update":
  4036. return void node.emitPatch({
  4037. op: "replace",
  4038. path: escapeJsonPath(change.name),
  4039. value: change.newValue.snapshot,
  4040. oldValue: change.oldValue ? change.oldValue.snapshot : undefined
  4041. }, node);
  4042. case "add":
  4043. return void node.emitPatch({
  4044. op: "add",
  4045. path: escapeJsonPath(change.name),
  4046. value: change.newValue.snapshot,
  4047. oldValue: undefined
  4048. }, node);
  4049. case "delete":
  4050. // a node got deleted, get the old snapshot and make the node die
  4051. var oldSnapshot = change.oldValue.snapshot;
  4052. change.oldValue.die();
  4053. // emit the patch
  4054. return void node.emitPatch({
  4055. op: "remove",
  4056. path: escapeJsonPath(change.name),
  4057. oldValue: oldSnapshot
  4058. }, node);
  4059. }
  4060. };
  4061. MapType.prototype.applyPatchLocally = function (node, subpath, patch) {
  4062. var target = node.storedValue;
  4063. switch (patch.op) {
  4064. case "add":
  4065. case "replace":
  4066. target.set(subpath, patch.value);
  4067. break;
  4068. case "remove":
  4069. target.delete(subpath);
  4070. break;
  4071. }
  4072. };
  4073. MapType.prototype.applySnapshot = function (node, snapshot) {
  4074. typecheckInternal(this, snapshot);
  4075. var target = node.storedValue;
  4076. var currentKeys = {};
  4077. Array.from(target.keys()).forEach(function (key) {
  4078. currentKeys[key] = false;
  4079. });
  4080. if (snapshot) {
  4081. // Don't use target.replace, as it will throw away all existing items first
  4082. for (var key in snapshot) {
  4083. target.set(key, snapshot[key]);
  4084. currentKeys["" + key] = true;
  4085. }
  4086. }
  4087. Object.keys(currentKeys).forEach(function (key) {
  4088. if (currentKeys[key] === false)
  4089. target.delete(key);
  4090. });
  4091. };
  4092. MapType.prototype.getChildType = function () {
  4093. return this._subType;
  4094. };
  4095. MapType.prototype.isValidSnapshot = function (value, context) {
  4096. var _this = this;
  4097. if (!isPlainObject(value)) {
  4098. return typeCheckFailure(context, value, "Value is not a plain object");
  4099. }
  4100. return flattenTypeErrors(Object.keys(value).map(function (path) {
  4101. return _this._subType.validate(value[path], getContextForPath(context, path, _this._subType));
  4102. }));
  4103. };
  4104. MapType.prototype.getDefaultSnapshot = function () {
  4105. return EMPTY_OBJECT;
  4106. };
  4107. MapType.prototype.removeChild = function (node, subpath) {
  4108. node.storedValue.delete(subpath);
  4109. };
  4110. __decorate([
  4111. mobx.action
  4112. ], MapType.prototype, "applySnapshot", null);
  4113. return MapType;
  4114. }(ComplexType));
  4115. /**
  4116. * `types.map` - Creates a key based collection type who's children are all of a uniform declared type.
  4117. * If the type stored in a map has an identifier, it is mandatory to store the child under that identifier in the map.
  4118. *
  4119. * This type will always produce [observable maps](https://mobx.js.org/refguide/map.html)
  4120. *
  4121. * Example:
  4122. * ```ts
  4123. * const Todo = types.model({
  4124. * id: types.identifier,
  4125. * task: types.string
  4126. * })
  4127. *
  4128. * const TodoStore = types.model({
  4129. * todos: types.map(Todo)
  4130. * })
  4131. *
  4132. * const s = TodoStore.create({ todos: {} })
  4133. * unprotect(s)
  4134. * s.todos.set(17, { task: "Grab coffee", id: 17 })
  4135. * s.todos.put({ task: "Grab cookie", id: 18 }) // put will infer key from the identifier
  4136. * console.log(s.todos.get(17).task) // prints: "Grab coffee"
  4137. * ```
  4138. *
  4139. * @param subtype
  4140. * @returns
  4141. */
  4142. function map(subtype) {
  4143. return new MapType("map<string, " + subtype.name + ">", subtype);
  4144. }
  4145. /**
  4146. * Returns if a given value represents a map type.
  4147. *
  4148. * @param type
  4149. * @returns `true` if it is a map type.
  4150. */
  4151. function isMapType(type) {
  4152. return isType(type) && (type.flags & TypeFlags.Map) > 0;
  4153. }
  4154. /**
  4155. * @internal
  4156. * @hidden
  4157. */
  4158. var ArrayType = /** @class */ (function (_super) {
  4159. __extends(ArrayType, _super);
  4160. function ArrayType(name, _subType, hookInitializers) {
  4161. if (hookInitializers === void 0) { hookInitializers = []; }
  4162. var _this = _super.call(this, name) || this;
  4163. _this._subType = _subType;
  4164. _this.flags = TypeFlags.Array;
  4165. _this.hookInitializers = [];
  4166. _this.hookInitializers = hookInitializers;
  4167. return _this;
  4168. }
  4169. ArrayType.prototype.hooks = function (hooks) {
  4170. var hookInitializers = this.hookInitializers.length > 0 ? this.hookInitializers.concat(hooks) : [hooks];
  4171. return new ArrayType(this.name, this._subType, hookInitializers);
  4172. };
  4173. ArrayType.prototype.instantiate = function (parent, subpath, environment, initialValue) {
  4174. return createObjectNode(this, parent, subpath, environment, initialValue);
  4175. };
  4176. ArrayType.prototype.initializeChildNodes = function (objNode, snapshot) {
  4177. if (snapshot === void 0) { snapshot = []; }
  4178. var subType = objNode.type._subType;
  4179. var result = {};
  4180. snapshot.forEach(function (item, index) {
  4181. var subpath = "" + index;
  4182. result[subpath] = subType.instantiate(objNode, subpath, undefined, item);
  4183. });
  4184. return result;
  4185. };
  4186. ArrayType.prototype.createNewInstance = function (childNodes) {
  4187. return mobx.observable.array(convertChildNodesToArray(childNodes), mobxShallow);
  4188. };
  4189. ArrayType.prototype.finalizeNewInstance = function (node, instance) {
  4190. mobx._getAdministration(instance).dehancer = node.unbox;
  4191. var type = node.type;
  4192. type.hookInitializers.forEach(function (initializer) {
  4193. var hooks = initializer(instance);
  4194. Object.keys(hooks).forEach(function (name) {
  4195. var hook = hooks[name];
  4196. var actionInvoker = createActionInvoker(instance, name, hook);
  4197. (!devMode() ? addHiddenFinalProp : addHiddenWritableProp)(instance, name, actionInvoker);
  4198. });
  4199. });
  4200. mobx.intercept(instance, this.willChange);
  4201. mobx.observe(instance, this.didChange);
  4202. };
  4203. ArrayType.prototype.describe = function () {
  4204. return this._subType.describe() + "[]";
  4205. };
  4206. ArrayType.prototype.getChildren = function (node) {
  4207. return node.storedValue.slice();
  4208. };
  4209. ArrayType.prototype.getChildNode = function (node, key) {
  4210. var index = Number(key);
  4211. if (index < node.storedValue.length)
  4212. return node.storedValue[index];
  4213. throw fail$1("Not a child: " + key);
  4214. };
  4215. ArrayType.prototype.willChange = function (change) {
  4216. var node = getStateTreeNode(change.object);
  4217. node.assertWritable({ subpath: "" + change.index });
  4218. var subType = node.type._subType;
  4219. var childNodes = node.getChildren();
  4220. switch (change.type) {
  4221. case "update":
  4222. {
  4223. if (change.newValue === change.object[change.index])
  4224. return null;
  4225. var updatedNodes = reconcileArrayChildren(node, subType, [childNodes[change.index]], [change.newValue], [change.index]);
  4226. if (!updatedNodes) {
  4227. return null;
  4228. }
  4229. change.newValue = updatedNodes[0];
  4230. }
  4231. break;
  4232. case "splice":
  4233. {
  4234. var index_1 = change.index, removedCount = change.removedCount, added = change.added;
  4235. var addedNodes = reconcileArrayChildren(node, subType, childNodes.slice(index_1, index_1 + removedCount), added, added.map(function (_, i) { return index_1 + i; }));
  4236. if (!addedNodes) {
  4237. return null;
  4238. }
  4239. change.added = addedNodes;
  4240. // update paths of remaining items
  4241. for (var i = index_1 + removedCount; i < childNodes.length; i++) {
  4242. childNodes[i].setParent(node, "" + (i + added.length - removedCount));
  4243. }
  4244. }
  4245. break;
  4246. }
  4247. return change;
  4248. };
  4249. ArrayType.prototype.getSnapshot = function (node) {
  4250. return node.getChildren().map(function (childNode) { return childNode.snapshot; });
  4251. };
  4252. ArrayType.prototype.processInitialSnapshot = function (childNodes) {
  4253. var processed = [];
  4254. Object.keys(childNodes).forEach(function (key) {
  4255. processed.push(childNodes[key].getSnapshot());
  4256. });
  4257. return processed;
  4258. };
  4259. ArrayType.prototype.didChange = function (change) {
  4260. var node = getStateTreeNode(change.object);
  4261. switch (change.type) {
  4262. case "update":
  4263. return void node.emitPatch({
  4264. op: "replace",
  4265. path: "" + change.index,
  4266. value: change.newValue.snapshot,
  4267. oldValue: change.oldValue ? change.oldValue.snapshot : undefined
  4268. }, node);
  4269. case "splice":
  4270. for (var i = change.removedCount - 1; i >= 0; i--)
  4271. node.emitPatch({
  4272. op: "remove",
  4273. path: "" + (change.index + i),
  4274. oldValue: change.removed[i].snapshot
  4275. }, node);
  4276. for (var i = 0; i < change.addedCount; i++)
  4277. node.emitPatch({
  4278. op: "add",
  4279. path: "" + (change.index + i),
  4280. value: node.getChildNode("" + (change.index + i)).snapshot,
  4281. oldValue: undefined
  4282. }, node);
  4283. return;
  4284. }
  4285. };
  4286. ArrayType.prototype.applyPatchLocally = function (node, subpath, patch) {
  4287. var target = node.storedValue;
  4288. var index = subpath === "-" ? target.length : Number(subpath);
  4289. switch (patch.op) {
  4290. case "replace":
  4291. target[index] = patch.value;
  4292. break;
  4293. case "add":
  4294. target.splice(index, 0, patch.value);
  4295. break;
  4296. case "remove":
  4297. target.splice(index, 1);
  4298. break;
  4299. }
  4300. };
  4301. ArrayType.prototype.applySnapshot = function (node, snapshot) {
  4302. typecheckInternal(this, snapshot);
  4303. var target = node.storedValue;
  4304. target.replace(snapshot);
  4305. };
  4306. ArrayType.prototype.getChildType = function () {
  4307. return this._subType;
  4308. };
  4309. ArrayType.prototype.isValidSnapshot = function (value, context) {
  4310. var _this = this;
  4311. if (!isArray(value)) {
  4312. return typeCheckFailure(context, value, "Value is not an array");
  4313. }
  4314. return flattenTypeErrors(value.map(function (item, index) {
  4315. return _this._subType.validate(item, getContextForPath(context, "" + index, _this._subType));
  4316. }));
  4317. };
  4318. ArrayType.prototype.getDefaultSnapshot = function () {
  4319. return EMPTY_ARRAY;
  4320. };
  4321. ArrayType.prototype.removeChild = function (node, subpath) {
  4322. node.storedValue.splice(Number(subpath), 1);
  4323. };
  4324. __decorate([
  4325. mobx.action
  4326. ], ArrayType.prototype, "applySnapshot", null);
  4327. return ArrayType;
  4328. }(ComplexType));
  4329. /**
  4330. * `types.array` - Creates an index based collection type who's children are all of a uniform declared type.
  4331. *
  4332. * This type will always produce [observable arrays](https://mobx.js.org/refguide/array.html)
  4333. *
  4334. * Example:
  4335. * ```ts
  4336. * const Todo = types.model({
  4337. * task: types.string
  4338. * })
  4339. *
  4340. * const TodoStore = types.model({
  4341. * todos: types.array(Todo)
  4342. * })
  4343. *
  4344. * const s = TodoStore.create({ todos: [] })
  4345. * unprotect(s) // needed to allow modifying outside of an action
  4346. * s.todos.push({ task: "Grab coffee" })
  4347. * console.log(s.todos[0]) // prints: "Grab coffee"
  4348. * ```
  4349. *
  4350. * @param subtype
  4351. * @returns
  4352. */
  4353. function array(subtype) {
  4354. assertIsType(subtype, 1);
  4355. return new ArrayType(subtype.name + "[]", subtype);
  4356. }
  4357. function reconcileArrayChildren(parent, childType, oldNodes, newValues, newPaths) {
  4358. var nothingChanged = true;
  4359. for (var i = 0;; i++) {
  4360. var hasNewNode = i <= newValues.length - 1;
  4361. var oldNode = oldNodes[i];
  4362. var newValue = hasNewNode ? newValues[i] : undefined;
  4363. var newPath = "" + newPaths[i];
  4364. // for some reason, instead of newValue we got a node, fallback to the storedValue
  4365. // TODO: https://github.com/mobxjs/mobx-state-tree/issues/340#issuecomment-325581681
  4366. if (isNode(newValue))
  4367. newValue = newValue.storedValue;
  4368. if (!oldNode && !hasNewNode) {
  4369. // both are empty, end
  4370. break;
  4371. }
  4372. else if (!hasNewNode) {
  4373. // new one does not exists
  4374. nothingChanged = false;
  4375. oldNodes.splice(i, 1);
  4376. if (oldNode instanceof ObjectNode) {
  4377. // since it is going to be returned by pop/splice/shift better create it before killing it
  4378. // so it doesn't end up in an undead state
  4379. oldNode.createObservableInstanceIfNeeded();
  4380. }
  4381. oldNode.die();
  4382. i--;
  4383. }
  4384. else if (!oldNode) {
  4385. // there is no old node, create it
  4386. // check if already belongs to the same parent. if so, avoid pushing item in. only swapping can occur.
  4387. if (isStateTreeNode(newValue) && getStateTreeNode(newValue).parent === parent) {
  4388. // this node is owned by this parent, but not in the reconcilable set, so it must be double
  4389. 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 + "'");
  4390. }
  4391. nothingChanged = false;
  4392. var newNode = valueAsNode(childType, parent, newPath, newValue);
  4393. oldNodes.splice(i, 0, newNode);
  4394. }
  4395. else if (areSame(oldNode, newValue)) {
  4396. // both are the same, reconcile
  4397. oldNodes[i] = valueAsNode(childType, parent, newPath, newValue, oldNode);
  4398. }
  4399. else {
  4400. // nothing to do, try to reorder
  4401. var oldMatch = undefined;
  4402. // find a possible candidate to reuse
  4403. for (var j = i; j < oldNodes.length; j++) {
  4404. if (areSame(oldNodes[j], newValue)) {
  4405. oldMatch = oldNodes.splice(j, 1)[0];
  4406. break;
  4407. }
  4408. }
  4409. nothingChanged = false;
  4410. var newNode = valueAsNode(childType, parent, newPath, newValue, oldMatch);
  4411. oldNodes.splice(i, 0, newNode);
  4412. }
  4413. }
  4414. return nothingChanged ? null : oldNodes;
  4415. }
  4416. /**
  4417. * Convert a value to a node at given parent and subpath. Attempts to reuse old node if possible and given.
  4418. */
  4419. function valueAsNode(childType, parent, subpath, newValue, oldNode) {
  4420. // ensure the value is valid-ish
  4421. typecheckInternal(childType, newValue);
  4422. function getNewNode() {
  4423. // the new value has a MST node
  4424. if (isStateTreeNode(newValue)) {
  4425. var childNode = getStateTreeNode(newValue);
  4426. childNode.assertAlive(EMPTY_OBJECT);
  4427. // the node lives here
  4428. if (childNode.parent !== null && childNode.parent === parent) {
  4429. childNode.setParent(parent, subpath);
  4430. return childNode;
  4431. }
  4432. }
  4433. // there is old node and new one is a value/snapshot
  4434. if (oldNode) {
  4435. return childType.reconcile(oldNode, newValue, parent, subpath);
  4436. }
  4437. // nothing to do, create from scratch
  4438. return childType.instantiate(parent, subpath, undefined, newValue);
  4439. }
  4440. var newNode = getNewNode();
  4441. if (oldNode && oldNode !== newNode) {
  4442. if (oldNode instanceof ObjectNode) {
  4443. // since it is going to be returned by pop/splice/shift better create it before killing it
  4444. // so it doesn't end up in an undead state
  4445. oldNode.createObservableInstanceIfNeeded();
  4446. }
  4447. oldNode.die();
  4448. }
  4449. return newNode;
  4450. }
  4451. /**
  4452. * Check if a node holds a value.
  4453. */
  4454. function areSame(oldNode, newValue) {
  4455. // never consider dead old nodes for reconciliation
  4456. if (!oldNode.isAlive) {
  4457. return false;
  4458. }
  4459. // the new value has the same node
  4460. if (isStateTreeNode(newValue)) {
  4461. var newNode = getStateTreeNode(newValue);
  4462. return newNode.isAlive && newNode === oldNode;
  4463. }
  4464. // the provided value is the snapshot of the old node
  4465. if (oldNode.snapshot === newValue) {
  4466. return true;
  4467. }
  4468. // new value is a snapshot with the correct identifier
  4469. return (oldNode instanceof ObjectNode &&
  4470. oldNode.identifier !== null &&
  4471. oldNode.identifierAttribute &&
  4472. isPlainObject(newValue) &&
  4473. oldNode.identifier === normalizeIdentifier(newValue[oldNode.identifierAttribute]) &&
  4474. oldNode.type.is(newValue));
  4475. }
  4476. /**
  4477. * Returns if a given value represents an array type.
  4478. *
  4479. * @param type
  4480. * @returns `true` if the type is an array type.
  4481. */
  4482. function isArrayType(type) {
  4483. return isType(type) && (type.flags & TypeFlags.Array) > 0;
  4484. }
  4485. var PRE_PROCESS_SNAPSHOT = "preProcessSnapshot";
  4486. var POST_PROCESS_SNAPSHOT = "postProcessSnapshot";
  4487. function objectTypeToString() {
  4488. return getStateTreeNode(this).toString();
  4489. }
  4490. var defaultObjectOptions = {
  4491. name: "AnonymousModel",
  4492. properties: {},
  4493. initializers: EMPTY_ARRAY
  4494. };
  4495. function toPropertiesObject(declaredProps) {
  4496. // loop through properties and ensures that all items are types
  4497. return Object.keys(declaredProps).reduce(function (props, key) {
  4498. var _a, _b, _c;
  4499. // warn if user intended a HOOK
  4500. if (key in Hook)
  4501. throw fail$1("Hook '" + key + "' was defined as property. Hooks should be defined as part of the actions");
  4502. // the user intended to use a view
  4503. var descriptor = Object.getOwnPropertyDescriptor(props, key);
  4504. if ("get" in descriptor) {
  4505. throw fail$1("Getters are not supported as properties. Please use views instead");
  4506. }
  4507. // undefined and null are not valid
  4508. var value = descriptor.value;
  4509. if (value === null || value === undefined) {
  4510. 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)`?");
  4511. // its a primitive, convert to its type
  4512. }
  4513. else if (isPrimitive(value)) {
  4514. return Object.assign({}, props, (_a = {},
  4515. _a[key] = optional(getPrimitiveFactoryFromValue(value), value),
  4516. _a));
  4517. // map defaults to empty object automatically for models
  4518. }
  4519. else if (value instanceof MapType) {
  4520. return Object.assign({}, props, (_b = {},
  4521. _b[key] = optional(value, {}),
  4522. _b));
  4523. }
  4524. else if (value instanceof ArrayType) {
  4525. return Object.assign({}, props, (_c = {}, _c[key] = optional(value, []), _c));
  4526. // its already a type
  4527. }
  4528. else if (isType(value)) {
  4529. return props;
  4530. // its a function, maybe the user wanted a view?
  4531. }
  4532. else if (devMode() && typeof value === "function") {
  4533. 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?");
  4534. // no other complex values
  4535. }
  4536. else if (devMode() && typeof value === "object") {
  4537. 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.");
  4538. // WTF did you pass in mate?
  4539. }
  4540. else {
  4541. throw fail$1("Invalid type definition for property '" + key + "', cannot infer a type from a value like '" + value + "' (" + typeof value + ")");
  4542. }
  4543. }, declaredProps);
  4544. }
  4545. /**
  4546. * @internal
  4547. * @hidden
  4548. */
  4549. var ModelType = /** @class */ (function (_super) {
  4550. __extends(ModelType, _super);
  4551. function ModelType(opts) {
  4552. var _this = _super.call(this, opts.name || defaultObjectOptions.name) || this;
  4553. _this.flags = TypeFlags.Object;
  4554. _this.named = function (name) {
  4555. return _this.cloneAndEnhance({ name: name });
  4556. };
  4557. _this.props = function (properties) {
  4558. return _this.cloneAndEnhance({ properties: properties });
  4559. };
  4560. _this.preProcessSnapshot = function (preProcessor) {
  4561. var currentPreprocessor = _this.preProcessor;
  4562. if (!currentPreprocessor)
  4563. return _this.cloneAndEnhance({ preProcessor: preProcessor });
  4564. else
  4565. return _this.cloneAndEnhance({
  4566. preProcessor: function (snapshot) { return currentPreprocessor(preProcessor(snapshot)); }
  4567. });
  4568. };
  4569. _this.postProcessSnapshot = function (postProcessor) {
  4570. var currentPostprocessor = _this.postProcessor;
  4571. if (!currentPostprocessor)
  4572. return _this.cloneAndEnhance({ postProcessor: postProcessor });
  4573. else
  4574. return _this.cloneAndEnhance({
  4575. postProcessor: function (snapshot) { return postProcessor(currentPostprocessor(snapshot)); }
  4576. });
  4577. };
  4578. Object.assign(_this, defaultObjectOptions, opts);
  4579. // ensures that any default value gets converted to its related type
  4580. _this.properties = toPropertiesObject(_this.properties);
  4581. freeze(_this.properties); // make sure nobody messes with it
  4582. _this.propertyNames = Object.keys(_this.properties);
  4583. _this.identifierAttribute = _this._getIdentifierAttribute();
  4584. return _this;
  4585. }
  4586. ModelType.prototype._getIdentifierAttribute = function () {
  4587. var identifierAttribute = undefined;
  4588. this.forAllProps(function (propName, propType) {
  4589. if (propType.flags & TypeFlags.Identifier) {
  4590. if (identifierAttribute)
  4591. throw fail$1("Cannot define property '" + propName + "' as object identifier, property '" + identifierAttribute + "' is already defined as identifier property");
  4592. identifierAttribute = propName;
  4593. }
  4594. });
  4595. return identifierAttribute;
  4596. };
  4597. ModelType.prototype.cloneAndEnhance = function (opts) {
  4598. return new ModelType({
  4599. name: opts.name || this.name,
  4600. properties: Object.assign({}, this.properties, opts.properties),
  4601. initializers: this.initializers.concat(opts.initializers || []),
  4602. preProcessor: opts.preProcessor || this.preProcessor,
  4603. postProcessor: opts.postProcessor || this.postProcessor
  4604. });
  4605. };
  4606. ModelType.prototype.actions = function (fn) {
  4607. var _this = this;
  4608. var actionInitializer = function (self) {
  4609. _this.instantiateActions(self, fn(self));
  4610. return self;
  4611. };
  4612. return this.cloneAndEnhance({ initializers: [actionInitializer] });
  4613. };
  4614. ModelType.prototype.instantiateActions = function (self, actions) {
  4615. // check if return is correct
  4616. if (!isPlainObject(actions))
  4617. throw fail$1("actions initializer should return a plain object containing actions");
  4618. // bind actions to the object created
  4619. Object.keys(actions).forEach(function (name) {
  4620. // warn if preprocessor was given
  4621. if (name === PRE_PROCESS_SNAPSHOT)
  4622. throw fail$1("Cannot define action '" + PRE_PROCESS_SNAPSHOT + "', it should be defined using 'type.preProcessSnapshot(fn)' instead");
  4623. // warn if postprocessor was given
  4624. if (name === POST_PROCESS_SNAPSHOT)
  4625. throw fail$1("Cannot define action '" + POST_PROCESS_SNAPSHOT + "', it should be defined using 'type.postProcessSnapshot(fn)' instead");
  4626. var action2 = actions[name];
  4627. // apply hook composition
  4628. var baseAction = self[name];
  4629. if (name in Hook && baseAction) {
  4630. var specializedAction_1 = action2;
  4631. action2 = function () {
  4632. baseAction.apply(null, arguments);
  4633. specializedAction_1.apply(null, arguments);
  4634. };
  4635. }
  4636. // the goal of this is to make sure actions using "this" can call themselves,
  4637. // while still allowing the middlewares to register them
  4638. var middlewares = action2.$mst_middleware; // make sure middlewares are not lost
  4639. var boundAction = action2.bind(actions);
  4640. boundAction.$mst_middleware = middlewares;
  4641. var actionInvoker = createActionInvoker(self, name, boundAction);
  4642. actions[name] = actionInvoker;
  4643. (!devMode() ? addHiddenFinalProp : addHiddenWritableProp)(self, name, actionInvoker);
  4644. });
  4645. };
  4646. ModelType.prototype.volatile = function (fn) {
  4647. var _this = this;
  4648. var stateInitializer = function (self) {
  4649. _this.instantiateVolatileState(self, fn(self));
  4650. return self;
  4651. };
  4652. return this.cloneAndEnhance({ initializers: [stateInitializer] });
  4653. };
  4654. ModelType.prototype.instantiateVolatileState = function (self, state) {
  4655. // check views return
  4656. if (!isPlainObject(state))
  4657. throw fail$1("volatile state initializer should return a plain object containing state");
  4658. mobx.set(self, state);
  4659. };
  4660. ModelType.prototype.extend = function (fn) {
  4661. var _this = this;
  4662. var initializer = function (self) {
  4663. var _a = fn(self), actions = _a.actions, views = _a.views, state = _a.state, rest = __rest(_a, ["actions", "views", "state"]);
  4664. for (var key in rest)
  4665. throw fail$1("The `extend` function should return an object with a subset of the fields 'actions', 'views' and 'state'. Found invalid key '" + key + "'");
  4666. if (state)
  4667. _this.instantiateVolatileState(self, state);
  4668. if (views)
  4669. _this.instantiateViews(self, views);
  4670. if (actions)
  4671. _this.instantiateActions(self, actions);
  4672. return self;
  4673. };
  4674. return this.cloneAndEnhance({ initializers: [initializer] });
  4675. };
  4676. ModelType.prototype.views = function (fn) {
  4677. var _this = this;
  4678. var viewInitializer = function (self) {
  4679. _this.instantiateViews(self, fn(self));
  4680. return self;
  4681. };
  4682. return this.cloneAndEnhance({ initializers: [viewInitializer] });
  4683. };
  4684. ModelType.prototype.instantiateViews = function (self, views) {
  4685. // check views return
  4686. if (!isPlainObject(views))
  4687. throw fail$1("views initializer should return a plain object containing views");
  4688. Object.keys(views).forEach(function (key) {
  4689. // is this a computed property?
  4690. var descriptor = Object.getOwnPropertyDescriptor(views, key);
  4691. if ("get" in descriptor) {
  4692. if (mobx.isComputedProp(self, key)) {
  4693. var computedValue = mobx._getAdministration(self, key);
  4694. // TODO: mobx currently does not allow redefining computes yet, pending #1121
  4695. // FIXME: this binds to the internals of mobx!
  4696. computedValue.derivation = descriptor.get;
  4697. computedValue.scope = self;
  4698. if (descriptor.set)
  4699. computedValue.setter = mobx.action(computedValue.name + "-setter", descriptor.set);
  4700. }
  4701. else {
  4702. mobx.computed(self, key, descriptor, true);
  4703. }
  4704. }
  4705. else if (typeof descriptor.value === "function") {
  4706. (!devMode() ? addHiddenFinalProp : addHiddenWritableProp)(self, key, descriptor.value);
  4707. }
  4708. else {
  4709. throw fail$1("A view member should either be a function or getter based property");
  4710. }
  4711. });
  4712. };
  4713. ModelType.prototype.instantiate = function (parent, subpath, environment, initialValue) {
  4714. var value = isStateTreeNode(initialValue)
  4715. ? initialValue
  4716. : this.applySnapshotPreProcessor(initialValue);
  4717. return createObjectNode(this, parent, subpath, environment, value);
  4718. // Optimization: record all prop- view- and action names after first construction, and generate an optimal base class
  4719. // that pre-reserves all these fields for fast object-member lookups
  4720. };
  4721. ModelType.prototype.initializeChildNodes = function (objNode, initialSnapshot) {
  4722. if (initialSnapshot === void 0) { initialSnapshot = {}; }
  4723. var type = objNode.type;
  4724. var result = {};
  4725. type.forAllProps(function (name, childType) {
  4726. result[name] = childType.instantiate(objNode, name, undefined, initialSnapshot[name]);
  4727. });
  4728. return result;
  4729. };
  4730. ModelType.prototype.createNewInstance = function (childNodes) {
  4731. return mobx.observable.object(childNodes, EMPTY_OBJECT, mobxShallow);
  4732. };
  4733. ModelType.prototype.finalizeNewInstance = function (node, instance) {
  4734. addHiddenFinalProp(instance, "toString", objectTypeToString);
  4735. this.forAllProps(function (name) {
  4736. mobx._interceptReads(instance, name, node.unbox);
  4737. });
  4738. this.initializers.reduce(function (self, fn) { return fn(self); }, instance);
  4739. mobx.intercept(instance, this.willChange);
  4740. mobx.observe(instance, this.didChange);
  4741. };
  4742. ModelType.prototype.willChange = function (chg) {
  4743. // TODO: mobx typings don't seem to take into account that newValue can be set even when removing a prop
  4744. var change = chg;
  4745. var node = getStateTreeNode(change.object);
  4746. var subpath = change.name;
  4747. node.assertWritable({ subpath: subpath });
  4748. var childType = node.type.properties[subpath];
  4749. // only properties are typed, state are stored as-is references
  4750. if (childType) {
  4751. typecheckInternal(childType, change.newValue);
  4752. change.newValue = childType.reconcile(node.getChildNode(subpath), change.newValue, node, subpath);
  4753. }
  4754. return change;
  4755. };
  4756. ModelType.prototype.didChange = function (chg) {
  4757. // TODO: mobx typings don't seem to take into account that newValue can be set even when removing a prop
  4758. var change = chg;
  4759. var childNode = getStateTreeNode(change.object);
  4760. var childType = childNode.type.properties[change.name];
  4761. if (!childType) {
  4762. // don't emit patches for volatile state
  4763. return;
  4764. }
  4765. var oldChildValue = change.oldValue ? change.oldValue.snapshot : undefined;
  4766. childNode.emitPatch({
  4767. op: "replace",
  4768. path: escapeJsonPath(change.name),
  4769. value: change.newValue.snapshot,
  4770. oldValue: oldChildValue
  4771. }, childNode);
  4772. };
  4773. ModelType.prototype.getChildren = function (node) {
  4774. var _this = this;
  4775. var res = [];
  4776. this.forAllProps(function (name) {
  4777. res.push(_this.getChildNode(node, name));
  4778. });
  4779. return res;
  4780. };
  4781. ModelType.prototype.getChildNode = function (node, key) {
  4782. if (!(key in this.properties))
  4783. throw fail$1("Not a value property: " + key);
  4784. var childNode = mobx._getAdministration(node.storedValue, key).value; // TODO: blegh!
  4785. if (!childNode)
  4786. throw fail$1("Node not available for property " + key);
  4787. return childNode;
  4788. };
  4789. ModelType.prototype.getSnapshot = function (node, applyPostProcess) {
  4790. var _this = this;
  4791. if (applyPostProcess === void 0) { applyPostProcess = true; }
  4792. var res = {};
  4793. this.forAllProps(function (name, type) {
  4794. mobx.getAtom(node.storedValue, name).reportObserved();
  4795. res[name] = _this.getChildNode(node, name).snapshot;
  4796. });
  4797. if (applyPostProcess) {
  4798. return this.applySnapshotPostProcessor(res);
  4799. }
  4800. return res;
  4801. };
  4802. ModelType.prototype.processInitialSnapshot = function (childNodes) {
  4803. var processed = {};
  4804. Object.keys(childNodes).forEach(function (key) {
  4805. processed[key] = childNodes[key].getSnapshot();
  4806. });
  4807. return this.applySnapshotPostProcessor(processed);
  4808. };
  4809. ModelType.prototype.applyPatchLocally = function (node, subpath, patch) {
  4810. if (!(patch.op === "replace" || patch.op === "add")) {
  4811. throw fail$1("object does not support operation " + patch.op);
  4812. }
  4813. node.storedValue[subpath] = patch.value;
  4814. };
  4815. ModelType.prototype.applySnapshot = function (node, snapshot) {
  4816. var preProcessedSnapshot = this.applySnapshotPreProcessor(snapshot);
  4817. typecheckInternal(this, preProcessedSnapshot);
  4818. this.forAllProps(function (name) {
  4819. node.storedValue[name] = preProcessedSnapshot[name];
  4820. });
  4821. };
  4822. ModelType.prototype.applySnapshotPreProcessor = function (snapshot) {
  4823. var processor = this.preProcessor;
  4824. return processor ? processor.call(null, snapshot) : snapshot;
  4825. };
  4826. ModelType.prototype.applySnapshotPostProcessor = function (snapshot) {
  4827. var postProcessor = this.postProcessor;
  4828. if (postProcessor)
  4829. return postProcessor.call(null, snapshot);
  4830. return snapshot;
  4831. };
  4832. ModelType.prototype.getChildType = function (propertyName) {
  4833. assertIsString(propertyName, 1);
  4834. return this.properties[propertyName];
  4835. };
  4836. ModelType.prototype.isValidSnapshot = function (value, context) {
  4837. var _this = this;
  4838. var snapshot = this.applySnapshotPreProcessor(value);
  4839. if (!isPlainObject(snapshot)) {
  4840. return typeCheckFailure(context, snapshot, "Value is not a plain object");
  4841. }
  4842. return flattenTypeErrors(this.propertyNames.map(function (key) {
  4843. return _this.properties[key].validate(snapshot[key], getContextForPath(context, key, _this.properties[key]));
  4844. }));
  4845. };
  4846. ModelType.prototype.forAllProps = function (fn) {
  4847. var _this = this;
  4848. this.propertyNames.forEach(function (key) { return fn(key, _this.properties[key]); });
  4849. };
  4850. ModelType.prototype.describe = function () {
  4851. var _this = this;
  4852. // optimization: cache
  4853. return ("{ " +
  4854. this.propertyNames.map(function (key) { return key + ": " + _this.properties[key].describe(); }).join("; ") +
  4855. " }");
  4856. };
  4857. ModelType.prototype.getDefaultSnapshot = function () {
  4858. return EMPTY_OBJECT;
  4859. };
  4860. ModelType.prototype.removeChild = function (node, subpath) {
  4861. node.storedValue[subpath] = undefined;
  4862. };
  4863. __decorate([
  4864. mobx.action
  4865. ], ModelType.prototype, "applySnapshot", null);
  4866. return ModelType;
  4867. }(ComplexType));
  4868. /**
  4869. * `types.model` - Creates a new model type by providing a name, properties, volatile state and actions.
  4870. *
  4871. * 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.
  4872. */
  4873. function model() {
  4874. var args = [];
  4875. for (var _i = 0; _i < arguments.length; _i++) {
  4876. args[_i] = arguments[_i];
  4877. }
  4878. var name = typeof args[0] === "string" ? args.shift() : "AnonymousModel";
  4879. var properties = args.shift() || {};
  4880. return new ModelType({ name: name, properties: properties });
  4881. }
  4882. /**
  4883. * `types.compose` - Composes a new model from one or more existing model types.
  4884. * This method can be invoked in two forms:
  4885. * Given 2 or more model types, the types are composed into a new Type.
  4886. * Given first parameter as a string and 2 or more model types,
  4887. * the types are composed into a new Type with the given name
  4888. */
  4889. function compose() {
  4890. var args = [];
  4891. for (var _i = 0; _i < arguments.length; _i++) {
  4892. args[_i] = arguments[_i];
  4893. }
  4894. // TODO: just join the base type names if no name is provided
  4895. var hasTypename = typeof args[0] === "string";
  4896. var typeName = hasTypename ? args[0] : "AnonymousModel";
  4897. if (hasTypename) {
  4898. args.shift();
  4899. }
  4900. // check all parameters
  4901. if (devMode()) {
  4902. args.forEach(function (type, i) {
  4903. assertArg(type, isModelType, "mobx-state-tree model type", hasTypename ? i + 2 : i + 1);
  4904. });
  4905. }
  4906. return args
  4907. .reduce(function (prev, cur) {
  4908. return prev.cloneAndEnhance({
  4909. name: prev.name + "_" + cur.name,
  4910. properties: cur.properties,
  4911. initializers: cur.initializers,
  4912. preProcessor: function (snapshot) {
  4913. return cur.applySnapshotPreProcessor(prev.applySnapshotPreProcessor(snapshot));
  4914. },
  4915. postProcessor: function (snapshot) {
  4916. return cur.applySnapshotPostProcessor(prev.applySnapshotPostProcessor(snapshot));
  4917. }
  4918. });
  4919. })
  4920. .named(typeName);
  4921. }
  4922. /**
  4923. * Returns if a given value represents a model type.
  4924. *
  4925. * @param type
  4926. * @returns
  4927. */
  4928. function isModelType(type) {
  4929. return isType(type) && (type.flags & TypeFlags.Object) > 0;
  4930. }
  4931. // TODO: implement CoreType using types.custom ?
  4932. /**
  4933. * @internal
  4934. * @hidden
  4935. */
  4936. var CoreType = /** @class */ (function (_super) {
  4937. __extends(CoreType, _super);
  4938. function CoreType(name, flags, checker, initializer) {
  4939. if (initializer === void 0) { initializer = identity; }
  4940. var _this = _super.call(this, name) || this;
  4941. _this.flags = flags;
  4942. _this.checker = checker;
  4943. _this.initializer = initializer;
  4944. _this.flags = flags;
  4945. return _this;
  4946. }
  4947. CoreType.prototype.describe = function () {
  4948. return this.name;
  4949. };
  4950. CoreType.prototype.instantiate = function (parent, subpath, environment, initialValue) {
  4951. return createScalarNode(this, parent, subpath, environment, initialValue);
  4952. };
  4953. CoreType.prototype.createNewInstance = function (snapshot) {
  4954. return this.initializer(snapshot);
  4955. };
  4956. CoreType.prototype.isValidSnapshot = function (value, context) {
  4957. if (isPrimitive(value) && this.checker(value)) {
  4958. return typeCheckSuccess();
  4959. }
  4960. var typeName = this.name === "Date" ? "Date or a unix milliseconds timestamp" : this.name;
  4961. return typeCheckFailure(context, value, "Value is not a " + typeName);
  4962. };
  4963. return CoreType;
  4964. }(SimpleType));
  4965. /**
  4966. * `types.string` - Creates a type that can only contain a string value.
  4967. * This type is used for string values by default
  4968. *
  4969. * Example:
  4970. * ```ts
  4971. * const Person = types.model({
  4972. * firstName: types.string,
  4973. * lastName: "Doe"
  4974. * })
  4975. * ```
  4976. */
  4977. // tslint:disable-next-line:variable-name
  4978. var string = new CoreType("string", TypeFlags.String, function (v) { return typeof v === "string"; });
  4979. /**
  4980. * `types.number` - Creates a type that can only contain a numeric value.
  4981. * This type is used for numeric values by default
  4982. *
  4983. * Example:
  4984. * ```ts
  4985. * const Vector = types.model({
  4986. * x: types.number,
  4987. * y: 1.5
  4988. * })
  4989. * ```
  4990. */
  4991. // tslint:disable-next-line:variable-name
  4992. var number = new CoreType("number", TypeFlags.Number, function (v) { return typeof v === "number"; });
  4993. /**
  4994. * `types.integer` - Creates a type that can only contain an integer value.
  4995. * This type is used for integer values by default
  4996. *
  4997. * Example:
  4998. * ```ts
  4999. * const Size = types.model({
  5000. * width: types.integer,
  5001. * height: 10
  5002. * })
  5003. * ```
  5004. */
  5005. // tslint:disable-next-line:variable-name
  5006. var integer = new CoreType("integer", TypeFlags.Integer, function (v) { return isInteger(v); });
  5007. /**
  5008. * `types.boolean` - Creates a type that can only contain a boolean value.
  5009. * This type is used for boolean values by default
  5010. *
  5011. * Example:
  5012. * ```ts
  5013. * const Thing = types.model({
  5014. * isCool: types.boolean,
  5015. * isAwesome: false
  5016. * })
  5017. * ```
  5018. */
  5019. // tslint:disable-next-line:variable-name
  5020. var boolean = new CoreType("boolean", TypeFlags.Boolean, function (v) { return typeof v === "boolean"; });
  5021. /**
  5022. * `types.null` - The type of the value `null`
  5023. */
  5024. var nullType = new CoreType("null", TypeFlags.Null, function (v) { return v === null; });
  5025. /**
  5026. * `types.undefined` - The type of the value `undefined`
  5027. */
  5028. var undefinedType = new CoreType("undefined", TypeFlags.Undefined, function (v) { return v === undefined; });
  5029. 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)); });
  5030. _DatePrimitive.getSnapshot = function (node) {
  5031. return node.storedValue.getTime();
  5032. };
  5033. /**
  5034. * `types.Date` - Creates a type that can only contain a javascript Date value.
  5035. *
  5036. * Example:
  5037. * ```ts
  5038. * const LogLine = types.model({
  5039. * timestamp: types.Date,
  5040. * })
  5041. *
  5042. * LogLine.create({ timestamp: new Date() })
  5043. * ```
  5044. */
  5045. var DatePrimitive = _DatePrimitive;
  5046. /**
  5047. * @internal
  5048. * @hidden
  5049. */
  5050. function getPrimitiveFactoryFromValue(value) {
  5051. switch (typeof value) {
  5052. case "string":
  5053. return string;
  5054. case "number":
  5055. return number; // In the future, isInteger(value) ? integer : number would be interesting, but would be too breaking for now
  5056. case "boolean":
  5057. return boolean;
  5058. case "object":
  5059. if (value instanceof Date)
  5060. return DatePrimitive;
  5061. }
  5062. throw fail$1("Cannot determine primitive type from value " + value);
  5063. }
  5064. /**
  5065. * Returns if a given value represents a primitive type.
  5066. *
  5067. * @param type
  5068. * @returns
  5069. */
  5070. function isPrimitiveType(type) {
  5071. return (isType(type) &&
  5072. (type.flags &
  5073. (TypeFlags.String |
  5074. TypeFlags.Number |
  5075. TypeFlags.Integer |
  5076. TypeFlags.Boolean |
  5077. TypeFlags.Date)) >
  5078. 0);
  5079. }
  5080. /**
  5081. * @internal
  5082. * @hidden
  5083. */
  5084. var Literal = /** @class */ (function (_super) {
  5085. __extends(Literal, _super);
  5086. function Literal(value) {
  5087. var _this = _super.call(this, JSON.stringify(value)) || this;
  5088. _this.flags = TypeFlags.Literal;
  5089. _this.value = value;
  5090. return _this;
  5091. }
  5092. Literal.prototype.instantiate = function (parent, subpath, environment, initialValue) {
  5093. return createScalarNode(this, parent, subpath, environment, initialValue);
  5094. };
  5095. Literal.prototype.describe = function () {
  5096. return JSON.stringify(this.value);
  5097. };
  5098. Literal.prototype.isValidSnapshot = function (value, context) {
  5099. if (isPrimitive(value) && value === this.value) {
  5100. return typeCheckSuccess();
  5101. }
  5102. return typeCheckFailure(context, value, "Value is not a literal " + JSON.stringify(this.value));
  5103. };
  5104. return Literal;
  5105. }(SimpleType));
  5106. /**
  5107. * `types.literal` - The literal type will return a type that will match only the exact given type.
  5108. * The given value must be a primitive, in order to be serialized to a snapshot correctly.
  5109. * You can use literal to match exact strings for example the exact male or female string.
  5110. *
  5111. * Example:
  5112. * ```ts
  5113. * const Person = types.model({
  5114. * name: types.string,
  5115. * gender: types.union(types.literal('male'), types.literal('female'))
  5116. * })
  5117. * ```
  5118. *
  5119. * @param value The value to use in the strict equal check
  5120. * @returns
  5121. */
  5122. function literal(value) {
  5123. // check that the given value is a primitive
  5124. assertArg(value, isPrimitive, "primitive", 1);
  5125. return new Literal(value);
  5126. }
  5127. /**
  5128. * Returns if a given value represents a literal type.
  5129. *
  5130. * @param type
  5131. * @returns
  5132. */
  5133. function isLiteralType(type) {
  5134. return isType(type) && (type.flags & TypeFlags.Literal) > 0;
  5135. }
  5136. var Refinement = /** @class */ (function (_super) {
  5137. __extends(Refinement, _super);
  5138. function Refinement(name, _subtype, _predicate, _message) {
  5139. var _this = _super.call(this, name) || this;
  5140. _this._subtype = _subtype;
  5141. _this._predicate = _predicate;
  5142. _this._message = _message;
  5143. return _this;
  5144. }
  5145. Object.defineProperty(Refinement.prototype, "flags", {
  5146. get: function () {
  5147. return this._subtype.flags | TypeFlags.Refinement;
  5148. },
  5149. enumerable: true,
  5150. configurable: true
  5151. });
  5152. Refinement.prototype.describe = function () {
  5153. return this.name;
  5154. };
  5155. Refinement.prototype.instantiate = function (parent, subpath, environment, initialValue) {
  5156. // create the child type
  5157. return this._subtype.instantiate(parent, subpath, environment, initialValue);
  5158. };
  5159. Refinement.prototype.isAssignableFrom = function (type) {
  5160. return this._subtype.isAssignableFrom(type);
  5161. };
  5162. Refinement.prototype.isValidSnapshot = function (value, context) {
  5163. var subtypeErrors = this._subtype.validate(value, context);
  5164. if (subtypeErrors.length > 0)
  5165. return subtypeErrors;
  5166. var snapshot = isStateTreeNode(value) ? getStateTreeNode(value).snapshot : value;
  5167. if (!this._predicate(snapshot)) {
  5168. return typeCheckFailure(context, value, this._message(value));
  5169. }
  5170. return typeCheckSuccess();
  5171. };
  5172. Refinement.prototype.reconcile = function (current, newValue, parent, subpath) {
  5173. return this._subtype.reconcile(current, newValue, parent, subpath);
  5174. };
  5175. Refinement.prototype.getSubTypes = function () {
  5176. return this._subtype;
  5177. };
  5178. return Refinement;
  5179. }(BaseType));
  5180. /**
  5181. * `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.
  5182. *
  5183. * @param name
  5184. * @param type
  5185. * @param predicate
  5186. * @returns
  5187. */
  5188. function refinement() {
  5189. var args = [];
  5190. for (var _i = 0; _i < arguments.length; _i++) {
  5191. args[_i] = arguments[_i];
  5192. }
  5193. var name = typeof args[0] === "string" ? args.shift() : isType(args[0]) ? args[0].name : null;
  5194. var type = args[0];
  5195. var predicate = args[1];
  5196. var message = args[2]
  5197. ? args[2]
  5198. : function (v) { return "Value does not respect the refinement predicate"; };
  5199. // ensures all parameters are correct
  5200. assertIsType(type, [1, 2]);
  5201. assertIsString(name, 1);
  5202. assertIsFunction(predicate, [2, 3]);
  5203. assertIsFunction(message, [3, 4]);
  5204. return new Refinement(name, type, predicate, message);
  5205. }
  5206. /**
  5207. * Returns if a given value is a refinement type.
  5208. *
  5209. * @param type
  5210. * @returns
  5211. */
  5212. function isRefinementType(type) {
  5213. return (type.flags & TypeFlags.Refinement) > 0;
  5214. }
  5215. /**
  5216. * `types.enumeration` - Can be used to create an string based enumeration.
  5217. * (note: this methods is just sugar for a union of string literals)
  5218. *
  5219. * Example:
  5220. * ```ts
  5221. * const TrafficLight = types.model({
  5222. * color: types.enumeration("Color", ["Red", "Orange", "Green"])
  5223. * })
  5224. * ```
  5225. *
  5226. * @param name descriptive name of the enumeration (optional)
  5227. * @param options possible values this enumeration can have
  5228. * @returns
  5229. */
  5230. function enumeration(name, options) {
  5231. var realOptions = typeof name === "string" ? options : name;
  5232. // check all options
  5233. if (devMode()) {
  5234. realOptions.forEach(function (option, i) {
  5235. assertIsString(option, i + 1);
  5236. });
  5237. }
  5238. var type = union.apply(void 0, __spread(realOptions.map(function (option) { return literal("" + option); })));
  5239. if (typeof name === "string")
  5240. type.name = name;
  5241. return type;
  5242. }
  5243. /**
  5244. * @internal
  5245. * @hidden
  5246. */
  5247. var Union = /** @class */ (function (_super) {
  5248. __extends(Union, _super);
  5249. function Union(name, _types, options) {
  5250. var _this = _super.call(this, name) || this;
  5251. _this._types = _types;
  5252. _this._eager = true;
  5253. options = __assign({ eager: true, dispatcher: undefined }, options);
  5254. _this._dispatcher = options.dispatcher;
  5255. if (!options.eager)
  5256. _this._eager = false;
  5257. return _this;
  5258. }
  5259. Object.defineProperty(Union.prototype, "flags", {
  5260. get: function () {
  5261. var result = TypeFlags.Union;
  5262. this._types.forEach(function (type) {
  5263. result |= type.flags;
  5264. });
  5265. return result;
  5266. },
  5267. enumerable: true,
  5268. configurable: true
  5269. });
  5270. Union.prototype.isAssignableFrom = function (type) {
  5271. return this._types.some(function (subType) { return subType.isAssignableFrom(type); });
  5272. };
  5273. Union.prototype.describe = function () {
  5274. return "(" + this._types.map(function (factory) { return factory.describe(); }).join(" | ") + ")";
  5275. };
  5276. Union.prototype.instantiate = function (parent, subpath, environment, initialValue) {
  5277. var type = this.determineType(initialValue, undefined);
  5278. if (!type)
  5279. throw fail$1("No matching type for union " + this.describe()); // can happen in prod builds
  5280. return type.instantiate(parent, subpath, environment, initialValue);
  5281. };
  5282. Union.prototype.reconcile = function (current, newValue, parent, subpath) {
  5283. var type = this.determineType(newValue, current.type);
  5284. if (!type)
  5285. throw fail$1("No matching type for union " + this.describe()); // can happen in prod builds
  5286. return type.reconcile(current, newValue, parent, subpath);
  5287. };
  5288. Union.prototype.determineType = function (value, reconcileCurrentType) {
  5289. // try the dispatcher, if defined
  5290. if (this._dispatcher) {
  5291. return this._dispatcher(value);
  5292. }
  5293. // find the most accomodating type
  5294. // if we are using reconciliation try the current node type first (fix for #1045)
  5295. if (reconcileCurrentType) {
  5296. if (reconcileCurrentType.is(value)) {
  5297. return reconcileCurrentType;
  5298. }
  5299. return this._types.filter(function (t) { return t !== reconcileCurrentType; }).find(function (type) { return type.is(value); });
  5300. }
  5301. else {
  5302. return this._types.find(function (type) { return type.is(value); });
  5303. }
  5304. };
  5305. Union.prototype.isValidSnapshot = function (value, context) {
  5306. if (this._dispatcher) {
  5307. return this._dispatcher(value).validate(value, context);
  5308. }
  5309. var allErrors = [];
  5310. var applicableTypes = 0;
  5311. for (var i = 0; i < this._types.length; i++) {
  5312. var type = this._types[i];
  5313. var errors = type.validate(value, context);
  5314. if (errors.length === 0) {
  5315. if (this._eager)
  5316. return typeCheckSuccess();
  5317. else
  5318. applicableTypes++;
  5319. }
  5320. else {
  5321. allErrors.push(errors);
  5322. }
  5323. }
  5324. if (applicableTypes === 1)
  5325. return typeCheckSuccess();
  5326. return typeCheckFailure(context, value, "No type is applicable for the union").concat(flattenTypeErrors(allErrors));
  5327. };
  5328. Union.prototype.getSubTypes = function () {
  5329. return this._types;
  5330. };
  5331. return Union;
  5332. }(BaseType));
  5333. /**
  5334. * `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`.
  5335. *
  5336. * @param optionsOrType
  5337. * @param otherTypes
  5338. * @returns
  5339. */
  5340. function union(optionsOrType) {
  5341. var otherTypes = [];
  5342. for (var _i = 1; _i < arguments.length; _i++) {
  5343. otherTypes[_i - 1] = arguments[_i];
  5344. }
  5345. var options = isType(optionsOrType) ? undefined : optionsOrType;
  5346. var types = isType(optionsOrType) ? __spread([optionsOrType], otherTypes) : otherTypes;
  5347. var name = "(" + types.map(function (type) { return type.name; }).join(" | ") + ")";
  5348. // check all options
  5349. if (devMode()) {
  5350. if (options) {
  5351. assertArg(options, function (o) { return isPlainObject(o); }, "object { eager?: boolean, dispatcher?: Function }", 1);
  5352. }
  5353. types.forEach(function (type, i) {
  5354. assertIsType(type, options ? i + 2 : i + 1);
  5355. });
  5356. }
  5357. return new Union(name, types, options);
  5358. }
  5359. /**
  5360. * Returns if a given value represents a union type.
  5361. *
  5362. * @param type
  5363. * @returns
  5364. */
  5365. function isUnionType(type) {
  5366. return (type.flags & TypeFlags.Union) > 0;
  5367. }
  5368. /**
  5369. * @hidden
  5370. * @internal
  5371. */
  5372. var OptionalValue = /** @class */ (function (_super) {
  5373. __extends(OptionalValue, _super);
  5374. function OptionalValue(_subtype, _defaultValue, optionalValues) {
  5375. var _this = _super.call(this, _subtype.name) || this;
  5376. _this._subtype = _subtype;
  5377. _this._defaultValue = _defaultValue;
  5378. _this.optionalValues = optionalValues;
  5379. return _this;
  5380. }
  5381. Object.defineProperty(OptionalValue.prototype, "flags", {
  5382. get: function () {
  5383. return this._subtype.flags | TypeFlags.Optional;
  5384. },
  5385. enumerable: true,
  5386. configurable: true
  5387. });
  5388. OptionalValue.prototype.describe = function () {
  5389. return this._subtype.describe() + "?";
  5390. };
  5391. OptionalValue.prototype.instantiate = function (parent, subpath, environment, initialValue) {
  5392. if (this.optionalValues.indexOf(initialValue) >= 0) {
  5393. var defaultInstanceOrSnapshot = this.getDefaultInstanceOrSnapshot();
  5394. return this._subtype.instantiate(parent, subpath, environment, defaultInstanceOrSnapshot);
  5395. }
  5396. return this._subtype.instantiate(parent, subpath, environment, initialValue);
  5397. };
  5398. OptionalValue.prototype.reconcile = function (current, newValue, parent, subpath) {
  5399. return this._subtype.reconcile(current, this.optionalValues.indexOf(newValue) < 0 && this._subtype.is(newValue)
  5400. ? newValue
  5401. : this.getDefaultInstanceOrSnapshot(), parent, subpath);
  5402. };
  5403. OptionalValue.prototype.getDefaultInstanceOrSnapshot = function () {
  5404. var defaultInstanceOrSnapshot = typeof this._defaultValue === "function"
  5405. ? this._defaultValue()
  5406. : this._defaultValue;
  5407. // while static values are already snapshots and checked on types.optional
  5408. // generator functions must always be rechecked just in case
  5409. if (typeof this._defaultValue === "function") {
  5410. typecheckInternal(this, defaultInstanceOrSnapshot);
  5411. }
  5412. return defaultInstanceOrSnapshot;
  5413. };
  5414. OptionalValue.prototype.isValidSnapshot = function (value, context) {
  5415. // defaulted values can be skipped
  5416. if (this.optionalValues.indexOf(value) >= 0) {
  5417. return typeCheckSuccess();
  5418. }
  5419. // bounce validation to the sub-type
  5420. return this._subtype.validate(value, context);
  5421. };
  5422. OptionalValue.prototype.isAssignableFrom = function (type) {
  5423. return this._subtype.isAssignableFrom(type);
  5424. };
  5425. OptionalValue.prototype.getSubTypes = function () {
  5426. return this._subtype;
  5427. };
  5428. return OptionalValue;
  5429. }(BaseType));
  5430. function checkOptionalPreconditions(type, defaultValueOrFunction) {
  5431. // make sure we never pass direct instances
  5432. if (typeof defaultValueOrFunction !== "function" && isStateTreeNode(defaultValueOrFunction)) {
  5433. throw fail$1("default value cannot be an instance, pass a snapshot or a function that creates an instance/snapshot instead");
  5434. }
  5435. assertIsType(type, 1);
  5436. if (devMode()) {
  5437. // we only check default values if they are passed directly
  5438. // if they are generator functions they will be checked once they are generated
  5439. // we don't check generator function results here to avoid generating a node just for type-checking purposes
  5440. // which might generate side-effects
  5441. if (typeof defaultValueOrFunction !== "function") {
  5442. typecheckInternal(type, defaultValueOrFunction);
  5443. }
  5444. }
  5445. }
  5446. /**
  5447. * `types.optional` - Can be used to create a property with a default value.
  5448. *
  5449. * Depending on the third argument (`optionalValues`) there are two ways of operation:
  5450. * - If the argument is not provided, then if a value is not provided in the snapshot (`undefined` or missing),
  5451. * it will default to the provided `defaultValue`
  5452. * - If the argument is provided, then if the value in the snapshot matches one of the optional values inside the array then it will
  5453. * default to the provided `defaultValue`. Additionally, if one of the optional values inside the array is `undefined` then a missing
  5454. * property is also valid.
  5455. *
  5456. * Note that it is also possible to include values of the same type as the intended subtype as optional values,
  5457. * in this case the optional value will be transformed into the `defaultValue` (e.g. `types.optional(types.string, "unnamed", [undefined, ""])`
  5458. * will transform the snapshot values `undefined` (and therefore missing) and empty strings into the string `"unnamed"` when it gets
  5459. * instantiated).
  5460. *
  5461. * If `defaultValue` is a function, the function will be invoked for every new instance.
  5462. * Applying a snapshot in which the optional value is one of the optional values (or `undefined`/_not_ present if none are provided) causes the
  5463. * value to be reset.
  5464. *
  5465. * Example:
  5466. * ```ts
  5467. * const Todo = types.model({
  5468. * title: types.string,
  5469. * subtitle1: types.optional(types.string, "", [null]),
  5470. * subtitle2: types.optional(types.string, "", [null, undefined]),
  5471. * done: types.optional(types.boolean, false),
  5472. * created: types.optional(types.Date, () => new Date()),
  5473. * })
  5474. *
  5475. * // if done is missing / undefined it will become false
  5476. * // if created is missing / undefined it will get a freshly generated timestamp
  5477. * // if subtitle1 is null it will default to "", but it cannot be missing or undefined
  5478. * // if subtitle2 is null or undefined it will default to ""; since it can be undefined it can also be missing
  5479. * const todo = Todo.create({ title: "Get coffee", subtitle1: null })
  5480. * ```
  5481. *
  5482. * @param type
  5483. * @param defaultValueOrFunction
  5484. * @param optionalValues an optional array with zero or more primitive values (string, number, boolean, null or undefined)
  5485. * that will be converted into the default. `[ undefined ]` is assumed when none is provided
  5486. * @returns
  5487. */
  5488. function optional(type, defaultValueOrFunction, optionalValues) {
  5489. checkOptionalPreconditions(type, defaultValueOrFunction);
  5490. return new OptionalValue(type, defaultValueOrFunction, optionalValues ? optionalValues : undefinedAsOptionalValues);
  5491. }
  5492. var undefinedAsOptionalValues = [undefined];
  5493. /**
  5494. * Returns if a value represents an optional type.
  5495. *
  5496. * @template IT
  5497. * @param type
  5498. * @returns
  5499. */
  5500. function isOptionalType(type) {
  5501. return isType(type) && (type.flags & TypeFlags.Optional) > 0;
  5502. }
  5503. var optionalUndefinedType = optional(undefinedType, undefined);
  5504. var optionalNullType = optional(nullType, null);
  5505. /**
  5506. * `types.maybe` - Maybe will make a type nullable, and also optional.
  5507. * The value `undefined` will be used to represent nullability.
  5508. *
  5509. * @param type
  5510. * @returns
  5511. */
  5512. function maybe(type) {
  5513. assertIsType(type, 1);
  5514. return union(type, optionalUndefinedType);
  5515. }
  5516. /**
  5517. * `types.maybeNull` - Maybe will make a type nullable, and also optional.
  5518. * The value `null` will be used to represent no value.
  5519. *
  5520. * @param type
  5521. * @returns
  5522. */
  5523. function maybeNull(type) {
  5524. assertIsType(type, 1);
  5525. return union(type, optionalNullType);
  5526. }
  5527. var Late = /** @class */ (function (_super) {
  5528. __extends(Late, _super);
  5529. function Late(name, _definition) {
  5530. var _this = _super.call(this, name) || this;
  5531. _this._definition = _definition;
  5532. return _this;
  5533. }
  5534. Object.defineProperty(Late.prototype, "flags", {
  5535. get: function () {
  5536. return (this._subType ? this._subType.flags : 0) | TypeFlags.Late;
  5537. },
  5538. enumerable: true,
  5539. configurable: true
  5540. });
  5541. Late.prototype.getSubType = function (mustSucceed) {
  5542. if (!this._subType) {
  5543. var t = undefined;
  5544. try {
  5545. t = this._definition();
  5546. }
  5547. catch (e) {
  5548. if (e instanceof ReferenceError)
  5549. // can happen in strict ES5 code when a definition is self refering
  5550. t = undefined;
  5551. else
  5552. throw e;
  5553. }
  5554. if (mustSucceed && t === undefined)
  5555. throw fail$1("Late type seems to be used too early, the definition (still) returns undefined");
  5556. if (t) {
  5557. if (devMode() && !isType(t))
  5558. throw fail$1("Failed to determine subtype, make sure types.late returns a type definition.");
  5559. this._subType = t;
  5560. }
  5561. }
  5562. return this._subType;
  5563. };
  5564. Late.prototype.instantiate = function (parent, subpath, environment, initialValue) {
  5565. return this.getSubType(true).instantiate(parent, subpath, environment, initialValue);
  5566. };
  5567. Late.prototype.reconcile = function (current, newValue, parent, subpath) {
  5568. return this.getSubType(true).reconcile(current, newValue, parent, subpath);
  5569. };
  5570. Late.prototype.describe = function () {
  5571. var t = this.getSubType(false);
  5572. return t ? t.name : "<uknown late type>";
  5573. };
  5574. Late.prototype.isValidSnapshot = function (value, context) {
  5575. var t = this.getSubType(false);
  5576. if (!t) {
  5577. // See #916; the variable the definition closure is pointing to wasn't defined yet, so can't be evaluted yet here
  5578. return typeCheckSuccess();
  5579. }
  5580. return t.validate(value, context);
  5581. };
  5582. Late.prototype.isAssignableFrom = function (type) {
  5583. var t = this.getSubType(false);
  5584. return t ? t.isAssignableFrom(type) : false;
  5585. };
  5586. Late.prototype.getSubTypes = function () {
  5587. var subtype = this.getSubType(false);
  5588. return subtype ? subtype : cannotDetermineSubtype;
  5589. };
  5590. return Late;
  5591. }(BaseType));
  5592. /**
  5593. * `types.late` - Defines a type that gets implemented later. This is useful when you have to deal with circular dependencies.
  5594. * Please notice that when defining circular dependencies TypeScript isn't smart enough to inference them.
  5595. *
  5596. * Example:
  5597. * ```ts
  5598. * // TypeScript isn't smart enough to infer self referencing types.
  5599. * const Node = types.model({
  5600. * children: types.array(types.late((): IAnyModelType => Node)) // then typecast each array element to Instance<typeof Node>
  5601. * })
  5602. * ```
  5603. *
  5604. * @param name The name to use for the type that will be returned.
  5605. * @param type A function that returns the type that will be defined.
  5606. * @returns
  5607. */
  5608. function late(nameOrType, maybeType) {
  5609. var name = typeof nameOrType === "string" ? nameOrType : "late(" + nameOrType.toString() + ")";
  5610. var type = typeof nameOrType === "string" ? maybeType : nameOrType;
  5611. // checks that the type is actually a late type
  5612. if (devMode()) {
  5613. if (!(typeof type === "function" && type.length === 0))
  5614. throw fail$1("Invalid late type, expected a function with zero arguments that returns a type, got: " +
  5615. type);
  5616. }
  5617. return new Late(name, type);
  5618. }
  5619. /**
  5620. * Returns if a given value represents a late type.
  5621. *
  5622. * @param type
  5623. * @returns
  5624. */
  5625. function isLateType(type) {
  5626. return isType(type) && (type.flags & TypeFlags.Late) > 0;
  5627. }
  5628. /**
  5629. * @internal
  5630. * @hidden
  5631. */
  5632. var Frozen = /** @class */ (function (_super) {
  5633. __extends(Frozen, _super);
  5634. function Frozen(subType) {
  5635. var _this = _super.call(this, subType ? "frozen(" + subType.name + ")" : "frozen") || this;
  5636. _this.subType = subType;
  5637. _this.flags = TypeFlags.Frozen;
  5638. return _this;
  5639. }
  5640. Frozen.prototype.describe = function () {
  5641. return "<any immutable value>";
  5642. };
  5643. Frozen.prototype.instantiate = function (parent, subpath, environment, value) {
  5644. // create the node
  5645. return createScalarNode(this, parent, subpath, environment, deepFreeze(value));
  5646. };
  5647. Frozen.prototype.isValidSnapshot = function (value, context) {
  5648. if (!isSerializable(value)) {
  5649. return typeCheckFailure(context, value, "Value is not serializable and cannot be frozen");
  5650. }
  5651. if (this.subType)
  5652. return this.subType.validate(value, context);
  5653. return typeCheckSuccess();
  5654. };
  5655. return Frozen;
  5656. }(SimpleType));
  5657. var untypedFrozenInstance = new Frozen();
  5658. /**
  5659. * `types.frozen` - Frozen can be used to store any value that is serializable in itself (that is valid JSON).
  5660. * Frozen values need to be immutable or treated as if immutable. They need be serializable as well.
  5661. * Values stored in frozen will snapshotted as-is by MST, and internal changes will not be tracked.
  5662. *
  5663. * 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.
  5664. *
  5665. * Note: if you want to store free-form state that is mutable, or not serializeable, consider using volatile state instead.
  5666. *
  5667. * Frozen properties can be defined in three different ways
  5668. * 1. `types.frozen(SubType)` - provide a valid MST type and frozen will check if the provided data conforms the snapshot for that type
  5669. * 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
  5670. * 3. `types.frozen<TypeScriptType>()` - provide a typescript type, to help in strongly typing the field (design time only)
  5671. *
  5672. * Example:
  5673. * ```ts
  5674. * const GameCharacter = types.model({
  5675. * name: string,
  5676. * location: types.frozen({ x: 0, y: 0})
  5677. * })
  5678. *
  5679. * const hero = GameCharacter.create({
  5680. * name: "Mario",
  5681. * location: { x: 7, y: 4 }
  5682. * })
  5683. *
  5684. * hero.location = { x: 10, y: 2 } // OK
  5685. * hero.location.x = 7 // Not ok!
  5686. * ```
  5687. *
  5688. * ```ts
  5689. * type Point = { x: number, y: number }
  5690. * const Mouse = types.model({
  5691. * loc: types.frozen<Point>()
  5692. * })
  5693. * ```
  5694. *
  5695. * @param defaultValueOrType
  5696. * @returns
  5697. */
  5698. function frozen(arg) {
  5699. if (arguments.length === 0)
  5700. return untypedFrozenInstance;
  5701. else if (isType(arg))
  5702. return new Frozen(arg);
  5703. else
  5704. return optional(untypedFrozenInstance, arg);
  5705. }
  5706. /**
  5707. * Returns if a given value represents a frozen type.
  5708. *
  5709. * @param type
  5710. * @returns
  5711. */
  5712. function isFrozenType(type) {
  5713. return isType(type) && (type.flags & TypeFlags.Frozen) > 0;
  5714. }
  5715. function getInvalidationCause(hook) {
  5716. switch (hook) {
  5717. case Hook.beforeDestroy:
  5718. return "destroy";
  5719. case Hook.beforeDetach:
  5720. return "detach";
  5721. default:
  5722. return undefined;
  5723. }
  5724. }
  5725. var StoredReference = /** @class */ (function () {
  5726. function StoredReference(value, targetType) {
  5727. this.targetType = targetType;
  5728. if (isValidIdentifier(value)) {
  5729. this.identifier = value;
  5730. }
  5731. else if (isStateTreeNode(value)) {
  5732. var targetNode = getStateTreeNode(value);
  5733. if (!targetNode.identifierAttribute)
  5734. throw fail$1("Can only store references with a defined identifier attribute.");
  5735. var id = targetNode.unnormalizedIdentifier;
  5736. if (id === null || id === undefined) {
  5737. throw fail$1("Can only store references to tree nodes with a defined identifier.");
  5738. }
  5739. this.identifier = id;
  5740. }
  5741. else {
  5742. throw fail$1("Can only store references to tree nodes or identifiers, got: '" + value + "'");
  5743. }
  5744. }
  5745. StoredReference.prototype.updateResolvedReference = function (node) {
  5746. var normalizedId = normalizeIdentifier(this.identifier);
  5747. var root = node.root;
  5748. var lastCacheModification = root.identifierCache.getLastCacheModificationPerId(normalizedId);
  5749. if (!this.resolvedReference ||
  5750. this.resolvedReference.lastCacheModification !== lastCacheModification) {
  5751. var targetType = this.targetType;
  5752. // reference was initialized with the identifier of the target
  5753. var target = root.identifierCache.resolve(targetType, normalizedId);
  5754. if (!target) {
  5755. throw new InvalidReferenceError("[mobx-state-tree] Failed to resolve reference '" + this.identifier + "' to type '" + this.targetType.name + "' (from node: " + node.path + ")");
  5756. }
  5757. this.resolvedReference = {
  5758. node: target,
  5759. lastCacheModification: lastCacheModification
  5760. };
  5761. }
  5762. };
  5763. Object.defineProperty(StoredReference.prototype, "resolvedValue", {
  5764. get: function () {
  5765. this.updateResolvedReference(this.node);
  5766. return this.resolvedReference.node.value;
  5767. },
  5768. enumerable: true,
  5769. configurable: true
  5770. });
  5771. return StoredReference;
  5772. }());
  5773. /**
  5774. * @internal
  5775. * @hidden
  5776. */
  5777. var InvalidReferenceError = /** @class */ (function (_super) {
  5778. __extends(InvalidReferenceError, _super);
  5779. function InvalidReferenceError(m) {
  5780. var _this = _super.call(this, m) || this;
  5781. Object.setPrototypeOf(_this, InvalidReferenceError.prototype);
  5782. return _this;
  5783. }
  5784. return InvalidReferenceError;
  5785. }(Error));
  5786. /**
  5787. * @internal
  5788. * @hidden
  5789. */
  5790. var BaseReferenceType = /** @class */ (function (_super) {
  5791. __extends(BaseReferenceType, _super);
  5792. function BaseReferenceType(targetType, onInvalidated) {
  5793. var _this = _super.call(this, "reference(" + targetType.name + ")") || this;
  5794. _this.targetType = targetType;
  5795. _this.onInvalidated = onInvalidated;
  5796. _this.flags = TypeFlags.Reference;
  5797. return _this;
  5798. }
  5799. BaseReferenceType.prototype.describe = function () {
  5800. return this.name;
  5801. };
  5802. BaseReferenceType.prototype.isAssignableFrom = function (type) {
  5803. return this.targetType.isAssignableFrom(type);
  5804. };
  5805. BaseReferenceType.prototype.isValidSnapshot = function (value, context) {
  5806. return isValidIdentifier(value)
  5807. ? typeCheckSuccess()
  5808. : typeCheckFailure(context, value, "Value is not a valid identifier, which is a string or a number");
  5809. };
  5810. BaseReferenceType.prototype.fireInvalidated = function (cause, storedRefNode, referenceId, refTargetNode) {
  5811. // to actually invalidate a reference we need an alive parent,
  5812. // since it is a scalar value (immutable-ish) and we need to change it
  5813. // from the parent
  5814. var storedRefParentNode = storedRefNode.parent;
  5815. if (!storedRefParentNode || !storedRefParentNode.isAlive) {
  5816. return;
  5817. }
  5818. var storedRefParentValue = storedRefParentNode.storedValue;
  5819. if (!storedRefParentValue) {
  5820. return;
  5821. }
  5822. this.onInvalidated({
  5823. cause: cause,
  5824. parent: storedRefParentValue,
  5825. invalidTarget: refTargetNode ? refTargetNode.storedValue : undefined,
  5826. invalidId: referenceId,
  5827. replaceRef: function (newRef) {
  5828. applyPatch(storedRefNode.root.storedValue, {
  5829. op: "replace",
  5830. value: newRef,
  5831. path: storedRefNode.path
  5832. });
  5833. },
  5834. removeRef: function () {
  5835. if (isModelType(storedRefParentNode.type)) {
  5836. this.replaceRef(undefined);
  5837. }
  5838. else {
  5839. applyPatch(storedRefNode.root.storedValue, {
  5840. op: "remove",
  5841. path: storedRefNode.path
  5842. });
  5843. }
  5844. }
  5845. });
  5846. };
  5847. BaseReferenceType.prototype.addTargetNodeWatcher = function (storedRefNode, referenceId) {
  5848. var _this = this;
  5849. // this will make sure the target node becomes created
  5850. var refTargetValue = this.getValue(storedRefNode);
  5851. if (!refTargetValue) {
  5852. return undefined;
  5853. }
  5854. var refTargetNode = getStateTreeNode(refTargetValue);
  5855. var hookHandler = function (_, refTargetNodeHook) {
  5856. var cause = getInvalidationCause(refTargetNodeHook);
  5857. if (!cause) {
  5858. return;
  5859. }
  5860. _this.fireInvalidated(cause, storedRefNode, referenceId, refTargetNode);
  5861. };
  5862. var refTargetDetachHookDisposer = refTargetNode.registerHook(Hook.beforeDetach, hookHandler);
  5863. var refTargetDestroyHookDisposer = refTargetNode.registerHook(Hook.beforeDestroy, hookHandler);
  5864. return function () {
  5865. refTargetDetachHookDisposer();
  5866. refTargetDestroyHookDisposer();
  5867. };
  5868. };
  5869. BaseReferenceType.prototype.watchTargetNodeForInvalidations = function (storedRefNode, identifier, customGetSet) {
  5870. var _this = this;
  5871. if (!this.onInvalidated) {
  5872. return;
  5873. }
  5874. var onRefTargetDestroyedHookDisposer;
  5875. // get rid of the watcher hook when the stored ref node is destroyed
  5876. // detached is ignored since scalar nodes (where the reference resides) cannot be detached
  5877. storedRefNode.registerHook(Hook.beforeDestroy, function () {
  5878. if (onRefTargetDestroyedHookDisposer) {
  5879. onRefTargetDestroyedHookDisposer();
  5880. }
  5881. });
  5882. var startWatching = function (sync) {
  5883. // re-create hook in case the stored ref gets reattached
  5884. if (onRefTargetDestroyedHookDisposer) {
  5885. onRefTargetDestroyedHookDisposer();
  5886. }
  5887. // make sure the target node is actually there and initialized
  5888. var storedRefParentNode = storedRefNode.parent;
  5889. var storedRefParentValue = storedRefParentNode && storedRefParentNode.storedValue;
  5890. if (storedRefParentNode && storedRefParentNode.isAlive && storedRefParentValue) {
  5891. var refTargetNodeExists = void 0;
  5892. if (customGetSet) {
  5893. refTargetNodeExists = !!customGetSet.get(identifier, storedRefParentValue);
  5894. }
  5895. else {
  5896. refTargetNodeExists = storedRefNode.root.identifierCache.has(_this.targetType, normalizeIdentifier(identifier));
  5897. }
  5898. if (!refTargetNodeExists) {
  5899. // we cannot change the reference in sync mode
  5900. // since we are in the middle of a reconciliation/instantiation and the change would be overwritten
  5901. // for those cases just let the wrong reference be assigned and fail upon usage
  5902. // (like current references do)
  5903. // this means that effectively this code will only run when it is created from a snapshot
  5904. if (!sync) {
  5905. _this.fireInvalidated("invalidSnapshotReference", storedRefNode, identifier, null);
  5906. }
  5907. }
  5908. else {
  5909. onRefTargetDestroyedHookDisposer = _this.addTargetNodeWatcher(storedRefNode, identifier);
  5910. }
  5911. }
  5912. };
  5913. if (storedRefNode.state === NodeLifeCycle.FINALIZED) {
  5914. // already attached, so the whole tree is ready
  5915. startWatching(true);
  5916. }
  5917. else {
  5918. if (!storedRefNode.isRoot) {
  5919. // start watching once the whole tree is ready
  5920. storedRefNode.root.registerHook(Hook.afterCreationFinalization, function () {
  5921. // make sure to attach it so it can start listening
  5922. if (storedRefNode.parent) {
  5923. storedRefNode.parent.createObservableInstanceIfNeeded();
  5924. }
  5925. });
  5926. }
  5927. // start watching once the node is attached somewhere / parent changes
  5928. storedRefNode.registerHook(Hook.afterAttach, function () {
  5929. startWatching(false);
  5930. });
  5931. }
  5932. };
  5933. return BaseReferenceType;
  5934. }(SimpleType));
  5935. /**
  5936. * @internal
  5937. * @hidden
  5938. */
  5939. var IdentifierReferenceType = /** @class */ (function (_super) {
  5940. __extends(IdentifierReferenceType, _super);
  5941. function IdentifierReferenceType(targetType, onInvalidated) {
  5942. return _super.call(this, targetType, onInvalidated) || this;
  5943. }
  5944. IdentifierReferenceType.prototype.getValue = function (storedRefNode) {
  5945. if (!storedRefNode.isAlive)
  5946. return undefined;
  5947. var storedRef = storedRefNode.storedValue;
  5948. return storedRef.resolvedValue;
  5949. };
  5950. IdentifierReferenceType.prototype.getSnapshot = function (storedRefNode) {
  5951. var ref = storedRefNode.storedValue;
  5952. return ref.identifier;
  5953. };
  5954. IdentifierReferenceType.prototype.instantiate = function (parent, subpath, environment, initialValue) {
  5955. var identifier = isStateTreeNode(initialValue)
  5956. ? getIdentifier(initialValue)
  5957. : initialValue;
  5958. var storedRef = new StoredReference(initialValue, this.targetType);
  5959. var storedRefNode = createScalarNode(this, parent, subpath, environment, storedRef);
  5960. storedRef.node = storedRefNode;
  5961. this.watchTargetNodeForInvalidations(storedRefNode, identifier, undefined);
  5962. return storedRefNode;
  5963. };
  5964. IdentifierReferenceType.prototype.reconcile = function (current, newValue, parent, subpath) {
  5965. if (!current.isDetaching && current.type === this) {
  5966. var compareByValue = isStateTreeNode(newValue);
  5967. var ref = current.storedValue;
  5968. if ((!compareByValue && ref.identifier === newValue) ||
  5969. (compareByValue && ref.resolvedValue === newValue)) {
  5970. current.setParent(parent, subpath);
  5971. return current;
  5972. }
  5973. }
  5974. var newNode = this.instantiate(parent, subpath, undefined, newValue);
  5975. current.die(); // noop if detaching
  5976. return newNode;
  5977. };
  5978. return IdentifierReferenceType;
  5979. }(BaseReferenceType));
  5980. /**
  5981. * @internal
  5982. * @hidden
  5983. */
  5984. var CustomReferenceType = /** @class */ (function (_super) {
  5985. __extends(CustomReferenceType, _super);
  5986. function CustomReferenceType(targetType, options, onInvalidated) {
  5987. var _this = _super.call(this, targetType, onInvalidated) || this;
  5988. _this.options = options;
  5989. return _this;
  5990. }
  5991. CustomReferenceType.prototype.getValue = function (storedRefNode) {
  5992. if (!storedRefNode.isAlive)
  5993. return undefined;
  5994. var referencedNode = this.options.get(storedRefNode.storedValue, storedRefNode.parent ? storedRefNode.parent.storedValue : null);
  5995. return referencedNode;
  5996. };
  5997. CustomReferenceType.prototype.getSnapshot = function (storedRefNode) {
  5998. return storedRefNode.storedValue;
  5999. };
  6000. CustomReferenceType.prototype.instantiate = function (parent, subpath, environment, newValue) {
  6001. var identifier = isStateTreeNode(newValue)
  6002. ? this.options.set(newValue, parent ? parent.storedValue : null)
  6003. : newValue;
  6004. var storedRefNode = createScalarNode(this, parent, subpath, environment, identifier);
  6005. this.watchTargetNodeForInvalidations(storedRefNode, identifier, this.options);
  6006. return storedRefNode;
  6007. };
  6008. CustomReferenceType.prototype.reconcile = function (current, newValue, parent, subpath) {
  6009. var newIdentifier = isStateTreeNode(newValue)
  6010. ? this.options.set(newValue, current ? current.storedValue : null)
  6011. : newValue;
  6012. if (!current.isDetaching &&
  6013. current.type === this &&
  6014. current.storedValue === newIdentifier) {
  6015. current.setParent(parent, subpath);
  6016. return current;
  6017. }
  6018. var newNode = this.instantiate(parent, subpath, undefined, newIdentifier);
  6019. current.die(); // noop if detaching
  6020. return newNode;
  6021. };
  6022. return CustomReferenceType;
  6023. }(BaseReferenceType));
  6024. /**
  6025. * `types.reference` - Creates a reference to another type, which should have defined an identifier.
  6026. * See also the [reference and identifiers](https://github.com/mobxjs/mobx-state-tree#references-and-identifiers) section.
  6027. */
  6028. function reference(subType, options) {
  6029. assertIsType(subType, 1);
  6030. if (devMode()) {
  6031. if (arguments.length === 2 && typeof arguments[1] === "string") {
  6032. // istanbul ignore next
  6033. throw fail$1("References with base path are no longer supported. Please remove the base path.");
  6034. }
  6035. }
  6036. var getSetOptions = options ? options : undefined;
  6037. var onInvalidated = options
  6038. ? options.onInvalidated
  6039. : undefined;
  6040. if (getSetOptions && (getSetOptions.get || getSetOptions.set)) {
  6041. if (devMode()) {
  6042. if (!getSetOptions.get || !getSetOptions.set) {
  6043. throw fail$1("reference options must either contain both a 'get' and a 'set' method or none of them");
  6044. }
  6045. }
  6046. return new CustomReferenceType(subType, {
  6047. get: getSetOptions.get,
  6048. set: getSetOptions.set
  6049. }, onInvalidated);
  6050. }
  6051. else {
  6052. return new IdentifierReferenceType(subType, onInvalidated);
  6053. }
  6054. }
  6055. /**
  6056. * Returns if a given value represents a reference type.
  6057. *
  6058. * @param type
  6059. * @returns
  6060. */
  6061. function isReferenceType(type) {
  6062. return (type.flags & TypeFlags.Reference) > 0;
  6063. }
  6064. /**
  6065. * `types.safeReference` - A safe reference is like a standard reference, except that it accepts the undefined value by default
  6066. * and automatically sets itself to undefined (when the parent is a model) / removes itself from arrays and maps
  6067. * when the reference it is pointing to gets detached/destroyed.
  6068. *
  6069. * The optional options parameter object accepts a parameter named `acceptsUndefined`, which is set to true by default, so it is suitable
  6070. * for model properties.
  6071. * When used inside collections (arrays/maps), it is recommended to set this option to false so it can't take undefined as value,
  6072. * which is usually the desired in those cases.
  6073. *
  6074. * Strictly speaking it is a `types.maybe(types.reference(X))` (when `acceptsUndefined` is set to true, the default) and
  6075. * `types.reference(X)` (when `acceptsUndefined` is set to false), both of them with a customized `onInvalidated` option.
  6076. *
  6077. * @param subType
  6078. * @param options
  6079. * @returns
  6080. */
  6081. function safeReference(subType, options) {
  6082. var refType = reference(subType, __assign(__assign({}, options), { onInvalidated: function (ev) {
  6083. ev.removeRef();
  6084. } }));
  6085. if (options && options.acceptsUndefined === false) {
  6086. return refType;
  6087. }
  6088. else {
  6089. return maybe(refType);
  6090. }
  6091. }
  6092. var BaseIdentifierType = /** @class */ (function (_super) {
  6093. __extends(BaseIdentifierType, _super);
  6094. function BaseIdentifierType(name, validType) {
  6095. var _this = _super.call(this, name) || this;
  6096. _this.validType = validType;
  6097. _this.flags = TypeFlags.Identifier;
  6098. return _this;
  6099. }
  6100. BaseIdentifierType.prototype.instantiate = function (parent, subpath, environment, initialValue) {
  6101. if (!parent || !(parent.type instanceof ModelType))
  6102. throw fail$1("Identifier types can only be instantiated as direct child of a model type");
  6103. return createScalarNode(this, parent, subpath, environment, initialValue);
  6104. };
  6105. BaseIdentifierType.prototype.reconcile = function (current, newValue, parent, subpath) {
  6106. // we don't consider detaching here since identifier are scalar nodes, and scalar nodes cannot be detached
  6107. if (current.storedValue !== newValue)
  6108. throw fail$1("Tried to change identifier from '" + current.storedValue + "' to '" + newValue + "'. Changing identifiers is not allowed.");
  6109. current.setParent(parent, subpath);
  6110. return current;
  6111. };
  6112. BaseIdentifierType.prototype.isValidSnapshot = function (value, context) {
  6113. if (typeof value !== this.validType) {
  6114. return typeCheckFailure(context, value, "Value is not a valid " + this.describe() + ", expected a " + this.validType);
  6115. }
  6116. return typeCheckSuccess();
  6117. };
  6118. return BaseIdentifierType;
  6119. }(SimpleType));
  6120. /**
  6121. * @internal
  6122. * @hidden
  6123. */
  6124. var IdentifierType = /** @class */ (function (_super) {
  6125. __extends(IdentifierType, _super);
  6126. function IdentifierType() {
  6127. var _this = _super.call(this, "identifier", "string") || this;
  6128. _this.flags = TypeFlags.Identifier;
  6129. return _this;
  6130. }
  6131. IdentifierType.prototype.describe = function () {
  6132. return "identifier";
  6133. };
  6134. return IdentifierType;
  6135. }(BaseIdentifierType));
  6136. /**
  6137. * @internal
  6138. * @hidden
  6139. */
  6140. var IdentifierNumberType = /** @class */ (function (_super) {
  6141. __extends(IdentifierNumberType, _super);
  6142. function IdentifierNumberType() {
  6143. return _super.call(this, "identifierNumber", "number") || this;
  6144. }
  6145. IdentifierNumberType.prototype.getSnapshot = function (node) {
  6146. return node.storedValue;
  6147. };
  6148. IdentifierNumberType.prototype.describe = function () {
  6149. return "identifierNumber";
  6150. };
  6151. return IdentifierNumberType;
  6152. }(BaseIdentifierType));
  6153. /**
  6154. * `types.identifier` - Identifiers are used to make references, lifecycle events and reconciling works.
  6155. * Inside a state tree, for each type can exist only one instance for each given identifier.
  6156. * For example there couldn't be 2 instances of user with id 1. If you need more, consider using references.
  6157. * Identifier can be used only as type property of a model.
  6158. * This type accepts as parameter the value type of the identifier field that can be either string or number.
  6159. *
  6160. * Example:
  6161. * ```ts
  6162. * const Todo = types.model("Todo", {
  6163. * id: types.identifier,
  6164. * title: types.string
  6165. * })
  6166. * ```
  6167. *
  6168. * @returns
  6169. */
  6170. var identifier = new IdentifierType();
  6171. /**
  6172. * `types.identifierNumber` - Similar to `types.identifier`. This one will serialize from / to a number when applying snapshots
  6173. *
  6174. * Example:
  6175. * ```ts
  6176. * const Todo = types.model("Todo", {
  6177. * id: types.identifierNumber,
  6178. * title: types.string
  6179. * })
  6180. * ```
  6181. *
  6182. * @returns
  6183. */
  6184. var identifierNumber = new IdentifierNumberType();
  6185. /**
  6186. * Returns if a given value represents an identifier type.
  6187. *
  6188. * @param type
  6189. * @returns
  6190. */
  6191. function isIdentifierType(type) {
  6192. return isType(type) && (type.flags & TypeFlags.Identifier) > 0;
  6193. }
  6194. /**
  6195. * @internal
  6196. * @hidden
  6197. */
  6198. function normalizeIdentifier(id) {
  6199. return "" + id;
  6200. }
  6201. /**
  6202. * @internal
  6203. * @hidden
  6204. */
  6205. function isValidIdentifier(id) {
  6206. return typeof id === "string" || typeof id === "number";
  6207. }
  6208. /**
  6209. * @internal
  6210. * @hidden
  6211. */
  6212. function assertIsValidIdentifier(id, argNumber) {
  6213. assertArg(id, isValidIdentifier, "string or number (identifier)", argNumber);
  6214. }
  6215. /**
  6216. * `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.
  6217. *
  6218. * The signature of the options is:
  6219. * ```ts
  6220. * export interface CustomTypeOptions<S, T> {
  6221. * // Friendly name
  6222. * name: string
  6223. * // given a serialized value, how to turn it into the target type
  6224. * fromSnapshot(snapshot: S): T
  6225. * // return the serialization of the current value
  6226. * toSnapshot(value: T): S
  6227. * // if true, this is a converted value, if false, it's a snapshot
  6228. * isTargetType(value: T | S): value is T
  6229. * // a non empty string is assumed to be a validation error
  6230. * getValidationMessage?(snapshot: S): string
  6231. * }
  6232. * ```
  6233. *
  6234. * Example:
  6235. * ```ts
  6236. * const DecimalPrimitive = types.custom<string, Decimal>({
  6237. * name: "Decimal",
  6238. * fromSnapshot(value: string) {
  6239. * return new Decimal(value)
  6240. * },
  6241. * toSnapshot(value: Decimal) {
  6242. * return value.toString()
  6243. * },
  6244. * isTargetType(value: string | Decimal): boolean {
  6245. * return value instanceof Decimal
  6246. * },
  6247. * getValidationMessage(value: string): string {
  6248. * if (/^-?\d+\.\d+$/.test(value)) return "" // OK
  6249. * return `'${value}' doesn't look like a valid decimal number`
  6250. * }
  6251. * })
  6252. *
  6253. * const Wallet = types.model({
  6254. * balance: DecimalPrimitive
  6255. * })
  6256. * ```
  6257. *
  6258. * @param options
  6259. * @returns
  6260. */
  6261. function custom(options) {
  6262. return new CustomType(options);
  6263. }
  6264. /**
  6265. * @internal
  6266. * @hidden
  6267. */
  6268. var CustomType = /** @class */ (function (_super) {
  6269. __extends(CustomType, _super);
  6270. function CustomType(options) {
  6271. var _this = _super.call(this, options.name) || this;
  6272. _this.options = options;
  6273. _this.flags = TypeFlags.Custom;
  6274. return _this;
  6275. }
  6276. CustomType.prototype.describe = function () {
  6277. return this.name;
  6278. };
  6279. CustomType.prototype.isValidSnapshot = function (value, context) {
  6280. if (this.options.isTargetType(value))
  6281. return typeCheckSuccess();
  6282. var typeError = this.options.getValidationMessage(value);
  6283. if (typeError) {
  6284. return typeCheckFailure(context, value, "Invalid value for type '" + this.name + "': " + typeError);
  6285. }
  6286. return typeCheckSuccess();
  6287. };
  6288. CustomType.prototype.getSnapshot = function (node) {
  6289. return this.options.toSnapshot(node.storedValue);
  6290. };
  6291. CustomType.prototype.instantiate = function (parent, subpath, environment, initialValue) {
  6292. var valueToStore = this.options.isTargetType(initialValue)
  6293. ? initialValue
  6294. : this.options.fromSnapshot(initialValue);
  6295. return createScalarNode(this, parent, subpath, environment, valueToStore);
  6296. };
  6297. CustomType.prototype.reconcile = function (current, value, parent, subpath) {
  6298. var isSnapshot = !this.options.isTargetType(value);
  6299. // in theory customs use scalar nodes which cannot be detached, but still...
  6300. if (!current.isDetaching) {
  6301. var unchanged = current.type === this &&
  6302. (isSnapshot ? value === current.snapshot : value === current.storedValue);
  6303. if (unchanged) {
  6304. current.setParent(parent, subpath);
  6305. return current;
  6306. }
  6307. }
  6308. var valueToStore = isSnapshot ? this.options.fromSnapshot(value) : value;
  6309. var newNode = this.instantiate(parent, subpath, undefined, valueToStore);
  6310. current.die(); // noop if detaching
  6311. return newNode;
  6312. };
  6313. return CustomType;
  6314. }(SimpleType));
  6315. // we import the types to re-export them inside types.
  6316. var types = {
  6317. enumeration: enumeration,
  6318. model: model,
  6319. compose: compose,
  6320. custom: custom,
  6321. reference: reference,
  6322. safeReference: safeReference,
  6323. union: union,
  6324. optional: optional,
  6325. literal: literal,
  6326. maybe: maybe,
  6327. maybeNull: maybeNull,
  6328. refinement: refinement,
  6329. string: string,
  6330. boolean: boolean,
  6331. number: number,
  6332. integer: integer,
  6333. Date: DatePrimitive,
  6334. map: map,
  6335. array: array,
  6336. frozen: frozen,
  6337. identifier: identifier,
  6338. identifierNumber: identifierNumber,
  6339. late: late,
  6340. undefined: undefinedType,
  6341. null: nullType,
  6342. snapshotProcessor: snapshotProcessor
  6343. };
  6344. exports.addDisposer = addDisposer;
  6345. exports.addMiddleware = addMiddleware;
  6346. exports.applyAction = applyAction;
  6347. exports.applyPatch = applyPatch;
  6348. exports.applySnapshot = applySnapshot;
  6349. exports.cast = cast;
  6350. exports.castFlowReturn = castFlowReturn;
  6351. exports.castToReferenceSnapshot = castToReferenceSnapshot;
  6352. exports.castToSnapshot = castToSnapshot;
  6353. exports.clone = clone;
  6354. exports.createActionTrackingMiddleware = createActionTrackingMiddleware;
  6355. exports.createActionTrackingMiddleware2 = createActionTrackingMiddleware2;
  6356. exports.decorate = decorate;
  6357. exports.destroy = destroy;
  6358. exports.detach = detach;
  6359. exports.escapeJsonPath = escapeJsonPath;
  6360. exports.flow = flow;
  6361. exports.getChildType = getChildType;
  6362. exports.getEnv = getEnv;
  6363. exports.getIdentifier = getIdentifier;
  6364. exports.getLivelinessChecking = getLivelinessChecking;
  6365. exports.getMembers = getMembers;
  6366. exports.getNodeId = getNodeId;
  6367. exports.getParent = getParent;
  6368. exports.getParentOfType = getParentOfType;
  6369. exports.getPath = getPath;
  6370. exports.getPathParts = getPathParts;
  6371. exports.getPropertyMembers = getPropertyMembers;
  6372. exports.getRelativePath = getRelativePath;
  6373. exports.getRoot = getRoot;
  6374. exports.getRunningActionContext = getRunningActionContext;
  6375. exports.getSnapshot = getSnapshot;
  6376. exports.getType = getType;
  6377. exports.hasParent = hasParent;
  6378. exports.hasParentOfType = hasParentOfType;
  6379. exports.isActionContextChildOf = isActionContextChildOf;
  6380. exports.isActionContextThisOrChildOf = isActionContextThisOrChildOf;
  6381. exports.isAlive = isAlive;
  6382. exports.isArrayType = isArrayType;
  6383. exports.isFrozenType = isFrozenType;
  6384. exports.isIdentifierType = isIdentifierType;
  6385. exports.isLateType = isLateType;
  6386. exports.isLiteralType = isLiteralType;
  6387. exports.isMapType = isMapType;
  6388. exports.isModelType = isModelType;
  6389. exports.isOptionalType = isOptionalType;
  6390. exports.isPrimitiveType = isPrimitiveType;
  6391. exports.isProtected = isProtected;
  6392. exports.isReferenceType = isReferenceType;
  6393. exports.isRefinementType = isRefinementType;
  6394. exports.isRoot = isRoot;
  6395. exports.isStateTreeNode = isStateTreeNode;
  6396. exports.isType = isType;
  6397. exports.isUnionType = isUnionType;
  6398. exports.isValidReference = isValidReference;
  6399. exports.joinJsonPath = joinJsonPath;
  6400. exports.onAction = onAction;
  6401. exports.onPatch = onPatch;
  6402. exports.onSnapshot = onSnapshot;
  6403. exports.process = process$1;
  6404. exports.protect = protect;
  6405. exports.recordActions = recordActions;
  6406. exports.recordPatches = recordPatches;
  6407. exports.resolveIdentifier = resolveIdentifier;
  6408. exports.resolvePath = resolvePath;
  6409. exports.setLivelinessChecking = setLivelinessChecking;
  6410. exports.setLivelynessChecking = setLivelynessChecking;
  6411. exports.splitJsonPath = splitJsonPath;
  6412. exports.tryReference = tryReference;
  6413. exports.tryResolve = tryResolve;
  6414. exports.typecheck = typecheck;
  6415. exports.types = types;
  6416. exports.unescapeJsonPath = unescapeJsonPath;
  6417. exports.unprotect = unprotect;
  6418. exports.walk = walk;