Full Code of mobxjs/mobx-state-tree for AI

master 24037f14c6b8 cached
206 files
1.4 MB
367.6k tokens
1111 symbols
1 requests
Download .txt
Showing preview only (1,542K chars total). Download the full file or copy to clipboard to get everything.
Repository: mobxjs/mobx-state-tree
Branch: master
Commit: 24037f14c6b8
Files: 206
Total size: 1.4 MB

Directory structure:
gitextract_v8l79haa/

├── .circleci/
│   └── config.yml
├── .dockerignore
├── .gitattributes
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   └── bug-report.md
│   ├── lock.yml
│   ├── pull_request_template.md
│   └── stale.yml
├── .gitignore
├── .husky/
│   └── pre-commit
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── Dockerfile
├── ISSUE_TEMPLATE.md
├── LICENSE
├── README.md
├── SECURITY.md
├── __tests__/
│   ├── core/
│   │   ├── 1525.test.ts
│   │   ├── 1664.test.ts
│   │   ├── 2230.test.ts
│   │   ├── __snapshots__/
│   │   │   ├── async.test.ts.snap
│   │   │   ├── custom-type.test.ts.snap
│   │   │   └── reference-custom.test.ts.snap
│   │   ├── action.test.ts
│   │   ├── actionTrackingMiddleware2.test.ts
│   │   ├── api.test.ts
│   │   ├── array.test.ts
│   │   ├── async.test.ts
│   │   ├── bigint.test.ts
│   │   ├── boolean.test.ts
│   │   ├── boxes-store.test.ts
│   │   ├── circular1.test.ts
│   │   ├── circular2.test.ts
│   │   ├── custom-type.test.ts
│   │   ├── date.test.ts
│   │   ├── deprecated.test.ts
│   │   ├── enum.test.ts
│   │   ├── env.test.ts
│   │   ├── frozen.test.ts
│   │   ├── hooks.test.ts
│   │   ├── identifier.test.ts
│   │   ├── jsonpatch.test.ts
│   │   ├── late.test.ts
│   │   ├── lazy.test.ts
│   │   ├── literal.test.ts
│   │   ├── map.test.ts
│   │   ├── model.test.ts
│   │   ├── name.test.ts
│   │   ├── node.test.ts
│   │   ├── number.test.ts
│   │   ├── object-node.test.ts
│   │   ├── object.test.ts
│   │   ├── optimizations.test.ts
│   │   ├── optional-extension.test.ts
│   │   ├── optional.test.ts
│   │   ├── parent-properties.test.ts
│   │   ├── pointer.test.ts
│   │   ├── primitives.test.ts
│   │   ├── protect.test.ts
│   │   ├── recordPatches.test.ts
│   │   ├── reference-custom.test.ts
│   │   ├── reference-onInvalidated.test.ts
│   │   ├── reference.test.ts
│   │   ├── refinement.test.ts
│   │   ├── reflection.test.ts
│   │   ├── snapshotProcessor.test.ts
│   │   ├── string.test.ts
│   │   ├── this.test.ts
│   │   ├── type-system.test.ts
│   │   ├── union.test.ts
│   │   └── volatile.test.ts
│   ├── perf/
│   │   ├── fixture-data.skip.ts
│   │   ├── fixture-models.skip.ts
│   │   ├── fixtures/
│   │   │   ├── fixture-data.ts
│   │   │   └── fixture-models.ts
│   │   ├── perf.skip.ts
│   │   ├── report.ts
│   │   ├── scenarios.ts
│   │   └── timer.ts
│   ├── setup.ts
│   ├── tsconfig.json
│   └── utils.test.ts
├── bun.lockb
├── bunfig.toml
├── changelog.md
├── docker-compose.yml
├── docs/
│   ├── .gitattributes
│   ├── API/
│   │   ├── index.md
│   │   └── interfaces/
│   │       ├── customtypeoptions.md
│   │       ├── functionwithflag.md
│   │       ├── iactioncontext.md
│   │       ├── iactionrecorder.md
│   │       ├── iactiontrackingmiddleware2call.md
│   │       ├── iactiontrackingmiddleware2hooks.md
│   │       ├── iactiontrackingmiddlewarehooks.md
│   │       ├── ianycomplextype.md
│   │       ├── ianymodeltype.md
│   │       ├── ianytype.md
│   │       ├── ihooks.md
│   │       ├── ijsonpatch.md
│   │       ├── imiddlewareevent.md
│   │       ├── imodelreflectiondata.md
│   │       ├── imodelreflectionpropertiesdata.md
│   │       ├── imodeltype.md
│   │       ├── ipatchrecorder.md
│   │       ├── ireversiblejsonpatch.md
│   │       ├── iserializedactioncall.md
│   │       ├── isimpletype.md
│   │       ├── isnapshotprocessor.md
│   │       ├── isnapshotprocessors.md
│   │       ├── itype.md
│   │       ├── ivalidationcontextentry.md
│   │       ├── ivalidationerror.md
│   │       ├── referenceoptionsgetset.md
│   │       ├── referenceoptionsoninvalidated.md
│   │       └── unionoptions.md
│   ├── API_header.md
│   ├── compare/
│   │   └── context-reducer-vs-mobx-state-tree.md
│   ├── concepts/
│   │   ├── actions.md
│   │   ├── async-actions.md
│   │   ├── dependency-injection.md
│   │   ├── listeners.md
│   │   ├── middleware.md
│   │   ├── patches.md
│   │   ├── react.md
│   │   ├── reconciliation.md
│   │   ├── references.md
│   │   ├── snapshots.md
│   │   ├── trees.md
│   │   ├── views.md
│   │   └── volatiles.md
│   ├── intro/
│   │   ├── examples.md
│   │   ├── getting-started.md
│   │   ├── installation.md
│   │   ├── philosophy.md
│   │   └── welcome.md
│   ├── overview/
│   │   ├── hooks.md
│   │   ├── types.md
│   │   └── utilties.md
│   ├── recipes/
│   │   ├── auto-generated-property-setter-actions.md
│   │   ├── mst-query.md
│   │   └── pre-built-form-types-with-mst-form-type.md
│   └── tips/
│       ├── circular-deps.md
│       ├── faq.md
│       ├── inheritance.md
│       ├── more-tips.md
│       ├── resources.md
│       ├── snapshots-as-values.md
│       └── typescript.md
├── jest.config.js
├── package.json
├── rollup.config.js
├── scripts/
│   ├── fix-docs-source-links.js
│   ├── generate-compose-type.js
│   └── generate-shared.js
├── src/
│   ├── core/
│   │   ├── action.ts
│   │   ├── actionContext.ts
│   │   ├── flow.ts
│   │   ├── json-patch.ts
│   │   ├── mst-operations.ts
│   │   ├── node/
│   │   │   ├── BaseNode.ts
│   │   │   ├── Hook.ts
│   │   │   ├── create-node.ts
│   │   │   ├── identifier-cache.ts
│   │   │   ├── livelinessChecking.ts
│   │   │   ├── node-utils.ts
│   │   │   ├── object-node.ts
│   │   │   └── scalar-node.ts
│   │   ├── process.ts
│   │   └── type/
│   │       ├── type-checker.ts
│   │       └── type.ts
│   ├── index.ts
│   ├── internal.ts
│   ├── middlewares/
│   │   ├── create-action-tracking-middleware.ts
│   │   ├── createActionTrackingMiddleware2.ts
│   │   └── on-action.ts
│   ├── types/
│   │   ├── complex-types/
│   │   │   ├── array.ts
│   │   │   ├── map.ts
│   │   │   └── model.ts
│   │   ├── index.ts
│   │   ├── primitives.ts
│   │   └── utility-types/
│   │       ├── custom.ts
│   │       ├── enumeration.ts
│   │       ├── frozen.ts
│   │       ├── identifier.ts
│   │       ├── late.ts
│   │       ├── lazy.ts
│   │       ├── literal.ts
│   │       ├── maybe.ts
│   │       ├── optional.ts
│   │       ├── reference.ts
│   │       ├── refinement.ts
│   │       ├── snapshotProcessor.ts
│   │       └── union.ts
│   └── utils.ts
├── test-results/
│   └── .gitkeep
├── tsconfig.json
├── tslint.json
├── typedocconfig.js
└── website/
    ├── bun.lockb
    ├── core/
    │   └── Footer.js
    ├── i18n/
    │   └── en.json
    ├── package.json
    ├── sidebars.json
    ├── siteConfig.js
    └── static/
        ├── css/
        │   └── custom.css
        └── index.html

================================================
FILE CONTENTS
================================================

================================================
FILE: .circleci/config.yml
================================================
version: 2.1

executors:
  my-executor:
    docker:
      - image: cimg/node:14.18.1
        environment:
          CI: true

orbs:
  node: circleci/node@4.7.0

jobs:
  # mobx-state-tree build
  build:
    executor: my-executor
    steps:
      - checkout

      - run:
          name: Install the latest version of bun
          command: curl -fsSL https://bun.sh/install | bash
      - run:
          name: Link bun
          command: sudo ln -s ~/.bun/bin/bun /usr/local/bin/
      - run:
          name: Install dependencies
          command: bun install
      - run:
          name: Build MST
          command: bun run build

      - persist_to_workspace:
          root: .
          paths:
            - ./*

  # Add new prettier check job
  check-prettier:
    executor: my-executor
    steps:
      - attach_workspace:
          at: .
      - run:
          name: Install the latest version of bun
          command: curl -fsSL https://bun.sh/install | bash
      - run:
          name: Link bun
          command: sudo ln -s ~/.bun/bin/bun /usr/local/bin/
      - run:
          name: Check code formatting
          command: bun run prettier:check

  # mobx-state-tree tests
  test-mst-dev:
    executor: my-executor
    steps:
      - attach_workspace:
          at: .

      - run:
          name: Install the latest version of bun
          command: curl -fsSL https://bun.sh/install | bash
      - run:
          name: Link bun
          command: sudo ln -s ~/.bun/bin/bun /usr/local/bin/
      - run: bun test:all

  test-mst-prod:
    executor: my-executor
    steps:
      - attach_workspace:
          at: .
      - run:
          name: Install the latest version of bun
          command: curl -fsSL https://bun.sh/install | bash
      - run:
          name: Link bun
          command: sudo ln -s ~/.bun/bin/bun /usr/local/bin/
      - run: bun test:prod

  test-size:
    executor: my-executor
    steps:
      - attach_workspace:
          at: .
      - run:
          name: Install the latest version of bun
          command: curl -fsSL https://bun.sh/install | bash
      - run:
          name: Link bun
          command: sudo ln -s ~/.bun/bin/bun /usr/local/bin/
      - run: bun run size

workflows:
  version: 2
  build-and-test:
    jobs:
      - build
      
      # Add prettier check to workflow
      - check-prettier:
          requires:
            - build

      - test-mst-dev:
          requires:
            - build
      - test-mst-prod:
          requires:
            - build
      # Temporarily disabled while we work to implement Bun testing
      # - test-size:
      #     requires:
      #       - build


================================================
FILE: .dockerignore
================================================
*/node_modules
*.log


================================================
FILE: .gitattributes
================================================
* text=auto

*.ts text eol=lf
*.json text eol=lf
*.md text eol=lf


================================================
FILE: .github/ISSUE_TEMPLATE/bug-report.md
================================================
---
name: Bug report
about: I think something is not working as it should
---

<!-- Not following the template might result in your issue being closed without further notice -->

**_Bug report_**

-   [ ] I've checked documentation and searched for existing issues [and discussions](https://github.com/mobxjs/mobx-state-tree/discussions)
-   [ ] I've made sure my project is based on the latest MST version
-   [ ] Fork [this](https://codesandbox.io/p/sandbox/mobx-state-tree-todolist-forked-pj732k) code sandbox or another minimal reproduction.

**Sandbox link or minimal reproduction code**

<!-- link to your sandbox or alternatively minimal reproduction code-->

**Describe the expected behavior**

<!-- What should happen? -->

**Describe the observed behavior**

<!-- What happens instead? -->


================================================
FILE: .github/lock.yml
================================================
# Configuration for Lock Threads - https://github.com/dessant/lock-threads

# Number of days of inactivity before a closed issue or pull request is locked
daysUntilLock: 60

# Skip issues and pull requests created before a given timestamp. Timestamp must
# follow ISO 8601 (`YYYY-MM-DD`). Set to `false` to disable
skipCreatedBefore: 2019-01-01

# Issues and pull requests with these labels will be ignored. Set to `[]` to disable
exemptLabels: []

# Label to add before locking, such as `outdated`. Set to `false` to disable
lockLabel: false

# Comment to post before locking. Set to `false` to disable
lockComment: >
  This thread has been automatically locked since there has not been
  any recent activity after it was closed. Please open a new issue for
  related bugs or questions.

# Assign `resolved` as the reason for locking. Set to `false` to disable
setLockReason: true

# Limit to only `issues` or `pulls`
only: issues


================================================
FILE: .github/pull_request_template.md
================================================
## What does this PR do and why?

<!--
Try to complete the sentence: "If this pull request is approved, it will...",
and add some information telling us why you're requesting this change

List any relevant GitHub issues, GitHub discussions, or other references.
-->

## Steps to validate locally

<!--
Describe how you checked this in your local development environment,
and how a reviewer might check it for themselves.

Consider writing tests, providing code snippets or sandboxes, or at least
a step-by-step instruction that reviewers can use to validate the change and consider
any unexpected behavior
-->


================================================
FILE: .github/stale.yml
================================================
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 10
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 4
# Issues with these labels will never be considered stale
exemptLabels:
    - brainstorming/wild idea
    - breaking change
    - bug
    - docs or examples
    - enhancement
    - has PR
    - help/PR welcome
    - require('@mweststrate')
    - never-stale
# Label to use when marking an issue as stale
staleLabel: stale
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
    This issue has been automatically marked as stale because it has not had
    recent activity in the last 10 days. It will be closed in 4 days if no further
    activity occurs. Thank you for your contributions.
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: false
# Limit to only `issues` or `pulls`
only: issues
# Comment to post when removing the stale label.
unmarkComment: >
    This issue has been automatically unmarked as stale. Please disregard previous warnings.


================================================
FILE: .gitignore
================================================
node_modules
*.log
lib
dist
coverage
.nyc_output
.idea
package-lock.json
.prettierignore
.vscode
.editorconfig
/test-results/**/*.xml
/website/build
.DS_Store
junit.xml

================================================
FILE: .husky/pre-commit
================================================
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

bun run lint-staged


================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct

## Our Pledge

We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.

We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.

## Our Standards

Examples of behavior that contributes to a positive environment for our
community include:

-   Demonstrating empathy and kindness toward other people
-   Being respectful of differing opinions, viewpoints, and experiences
-   Giving and gracefully accepting constructive feedback
-   Accepting responsibility and apologizing to those affected by our mistakes,
    and learning from the experience
-   Focusing on what is best not just for us as individuals, but for the
    overall community

Examples of unacceptable behavior include:

-   The use of sexualized language or imagery, and sexual attention or
    advances of any kind
-   Trolling, insulting or derogatory comments, and personal or political attacks
-   Public or private harassment
-   Publishing others' private information, such as a physical or email
    address, without their explicit permission
-   Other conduct which could reasonably be considered inappropriate in a
    professional setting

## Enforcement Responsibilities

Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.

Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.

## Scope

This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.

## Enforcement

All complaints will be reviewed and investigated promptly and fairly.

All community leaders are obligated to respect the privacy and security of the
reporter of any incident.

## Enforcement Guidelines

Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:

### 1. Correction

**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.

**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.

### 2. Warning

**Community Impact**: A violation through a single incident or series
of actions.

**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.

### 3. Temporary Ban

**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.

**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.

### 4. Permanent Ban

**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.

**Consequence**: A permanent ban from any sort of public interaction within
the community.

## Attribution

This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.

Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).

[homepage]: https://www.contributor-covenant.org

For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.


================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to MobX-State-Tree

Welcome to MobX-State-Tree! We're stoked that you want to contribute to our open-source project. Our community is essential in maintaining and improving the stability, test coverage, and documentation of MST. We really appreciate your time and interest in pitching in. Overall, we want to build useful software and have fun doing it - we hope you'll be able to join us!

## Table of Contents

1. [Getting Started](#getting-started)
2. [Contributing Guidelines](#contributing-guidelines)
3. [Reporting Bugs](#reporting-bugs)
4. [Code of Conduct](#code-of-conduct)

## Getting Started

Before you start contributing, please make sure you have:

- [Bun](https://bun.sh/) installed on your local machine.
- A [GitHub](https://github.com/) account, as you'll need it to create issues and submit pull requests.

Most of the documentation and community assumes some amount of familiarity with:

1. JavaScript
2. TypeScript
3. git
4. Using the command line
5. Experience with state management libraries (typically on the frontend, although there are plenty of applications using MST in other contexts).

If you don't feel comfortable with these concepts, we'd be happy to help you get started, but you may want to consider brushing up on them before digging into the codebase. Reach out in the [discussions section of our GitHub repository](https://github.com/mobxjs/mobx-state-tree/discussions) if you'd like pointers about where to start.

## Contributing Guidelines

### Prioritizing Stability Over New Features

The existing API for MobX-State-Tree is [already quite extensive](https://mobx-state-tree.js.org/intro/welcome). As such, issues and PRs about new features may take lower priority than bug fixes, improving existing features, and performance/TypeScript improvements. If you're looking to augment MST with new functionality, we encourage you to consider building your own third-party library around our project, or perhaps [contributing to the mst-middlewares package](https://github.com/coolsoftwaretyler/mst-middlewares). We'd be happy to help faciliate that work, especially if it keeps our API from expanding much further.

### Tests

To maintain our library's stability, we are always striving to improve test coverage, even where more tests might be redundant. Every PR is _required to add at least one test that directly exercises your code change_, even if that test may be duplicative of existing tests. If you do not include tests with your PR, we will ask you to do so before reviewing. If you open a PR and are unwilling to write tests, we may either write tests on your behalf, or close the PR. If you are uncomfortable writing tests or working with Jest (our current testing library), we would be happy to guide you. This requirement is not intended as a barrier to entry, but as a way for us to enforce and improve the stability of our long-lived library here. It also serves as a way to externally communicate how your change will (or perhaps how it will not) modify the behavior of MST. There's no documentation quite as good as a comprehensive test suite!

### Documentation Changes

Good documentation is crucial for our users. If your contribution involves changes to the library's behavior, please update the documentation accordingly. Not every PR is necessarily going to require documentation updates, but we encourage you to consider touching up documentation related to your code changes. If you're unsure about where to make changes, feel free to reach out to us, and we'll be happy to guide you.

When changing the API, commit the code changes first, then run `npm run build-docs` and commit the documentation separately.

### Submitting a Pull Request

1. Fork the MobX-State-Tree repository on GitHub to your own GitHub account.
2. Clone your fork to your local machine.
3. Create a new branch for your changes: `git checkout -b my-feature`.
4. Before starting, it's not a bad idea to `bun install && bun run build && bun run test:all` to check that your machine can run the full test suite to start.
5. Make your changes and ensure that all tests pass (including any new tests you have added).
6. Update the documentation if necessary.
7. Commit your changes: `git commit -m "Add my feature"`. Please consider [following conventional commit formatting](https://www.conventionalcommits.org/en/v1.0.0/).
8. Push your changes to your fork: `git push origin my-feature`.
9. Create a pull request on the MobX-State-Tree repository. We have a pull request template. If you fill that out and include examples of your changes, links to any issue(s) you're working on, and a good description of your PR, that would help us out a lot. If you skip those steps, we may ask you for clarification before reviewing your work.

Our team will review your pull request as soon as possible and provide feedback. Please be patient, as it may take some time to review and merge your contribution.

## Reporting Bugs

If you encounter a bug while using MobX-State-Tree, please help us by reporting it. To report a bug:

1. Check if the bug has already been reported by searching our [issue tracker](https://github.com/mobxjs/mobx-state-tree/issues).
2. If not, create a new issue, including as much detail as possible about the bug and steps to reproduce it. We have issue templates that will ask specific questions for you to help us understand the problem.

## Bigger PRs

If you want to contribute a large or significant change to MST, we'd love to connect with you ahead of time to make sure it fits in with our overall road map, meets our stability requirements, and make sure you are set up for success. Please consider [asking around in the discussion forum](https://github.com/mobxjs/mobx-state-tree/discussions) if you have a big idea you want to implement, or if you want to work on some existing big ideas out therein the communit.

## Code of Conduct

We strive to maintain a friendly and welcoming community. Please read and adhere to our [Code of Conduct](CODE_OF_CONDUCT.md) in all interactions within the MobX-State-Tree project.

Thank you for considering contributing to MobX-State-Tree. Your contributions help us make our library better for everyone. We appreciate your support and look forward to collaborating with you!


================================================
FILE: Dockerfile
================================================
FROM node:8.11.4

WORKDIR /app/website

EXPOSE 3000 35729
COPY ./docs /app/docs
COPY ./website /app/website
RUN yarn install

CMD ["yarn", "start"]


================================================
FILE: ISSUE_TEMPLATE.md
================================================
**If your issue isn't a bug report, please consider using discussion threads instead of opening an issue: https://github.com/mobxjs/mobx-state-tree/discussions**


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2016 Michel Weststrate

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
<img src="website/static/img/mobx-state-tree-logo-gradient.png" alt="logo" height="120" align="right" />

# mobx-state-tree

[![npm version](https://badge.fury.io/js/mobx-state-tree.svg)](https://badge.fury.io/js/mobx-state-tree)
[![CircleCI](https://circleci.com/gh/mobxjs/mobx-state-tree.svg?style=svg)](https://circleci.com/gh/mobxjs/mobx-state-tree)
[![Have a question? Ask on GitHub Discussions!](https://img.shields.io/badge/Have%20a%20question%3F-Ask%20on%20GitHub%20Discussions!-blue)](https://github.com/mobxjs/mobx-state-tree/discussions)

## What is mobx-state-tree?

Technically speaking, mobx-state-tree (also known as MST) is a state container system built on [MobX](https://github.com/mobxjs/mobx), a functional reactive state library.

This may not mean much to you, and that’s okay. I’ll explain it like this: **MobX is a state management "engine", and MobX-State-Tree gives it structure and common tools you need for your app.** MST is valuable in a large team but also useful in smaller applications when you expect your code to scale rapidly. And if we compare it to Redux, MST offers better performance and much less boilerplate code than Redux!

MobX is [one of the most popular Redux alternatives](https://2019.stateofjs.com/data-layer/mobx/) and is used (along with MobX-State-Tree) by companies worldwide. MST plays very well with TypeScript, React, and React Native, especially when paired with [mobx-react-lite](https://github.com/mobxjs/mobx/tree/main/packages/mobx-react-lite). It supports multiple stores, async actions and side effects, enables extremely targeted re-renders for React apps, and much more -- all in a package with _zero dependencies_ other than MobX itself.

_Note: you don't need to know how to use MobX in order to use MST._

# Getting started

See the [Getting started](https://mobx-state-tree.js.org/intro/getting-started) tutorial or follow the free [egghead.io course](https://egghead.io/courses/manage-application-state-with-mobx-state-tree).

👉 Official docs can be found at [http://mobx-state-tree.js.org/](http://mobx-state-tree.js.org/)

## Quick Code Example

There's nothing quite like looking at some code to get a feel for a library. Check out this small example of an author and list of tweets by that author.

```js
import { types } from "mobx-state-tree" // alternatively: import { t } from "mobx-state-tree"

// Define a couple models
const Author = types.model({
  id: types.identifier,
  firstName: types.string,
  lastName: types.string
})
const Tweet = types.model({
  id: types.identifier,
  author: types.reference(Author), // stores just the `id` reference!
  body: types.string,
  timestamp: types.number
})

// Define a store just like a model
const RootStore = types.model({
  authors: types.array(Author),
  tweets: types.array(Tweet)
})

// Instantiate a couple model instances
const jamon = Author.create({
  id: "jamon",
  firstName: "Jamon",
  lastName: "Holmgren"
})

const tweet = Tweet.create({
  id: "1",
  author: jamon.id, // just the ID needed here
  body: "Hello world!",
  timestamp: Date.now()
})

// Now instantiate the store!
const rootStore = RootStore.create({
  authors: [jamon],
  tweets: [tweet]
})

// Ready to use in a React component, if that's your target.
import { observer } from "mobx-react-lite"
const MyComponent = observer((props) => {
  return <div>Hello, {rootStore.authors[0].firstName}!</div>
})

// Note: since this component is "observed", any changes to rootStore.authors[0].firstName
// will result in a re-render! If you're not using React, you can also "listen" to changes
// using `onSnapshot`: https://mobx-state-tree.js.org/concepts/snapshots
```

## Thanks!

- [Michel Weststrate](https://twitter.com/mweststrate) for creating MobX, MobX-State-Tree, and MobX-React.
- [Infinite Red](https://infinite.red) for supporting ongoing maintenance on MST.
- [Mendix](https://mendix.com) for sponsoring and providing the opportunity to work on exploratory projects like MST.
- [Dan Abramov](https://twitter.com/dan_abramov)'s work on [Redux](http://redux.js.org) has strongly influenced the idea of snapshots and transactional actions in MST.
- [Giulio Canti](https://twitter.com/GiulioCanti)'s work on [tcomb](http://github.com/gcanti/tcomb) and type systems in general has strongly influenced the type system of MST.
- All the early adopters encouraging to pursue this whole idea and proving it is something feasible.


================================================
FILE: SECURITY.md
================================================
## Security contact information

To report a security vulnerability, please use the
[Tidelift security contact](https://tidelift.com/security).
Tidelift will coordinate the fix and disclosure.


================================================
FILE: __tests__/core/1525.test.ts
================================================
import { types, Instance } from "../../src/index"
import { describe, it } from "bun:test"

describe("1525. Model instance maybe fields becoming TypeScript optional fields when included in a types.union", () => {
    it("does not throw a typescript error", () => {
        const Model = types.model("myModel", {
            foo: types.string,
            bar: types.maybe(types.integer)
        })

        const Store = types.model("store", {
            itemWithoutIssue: Model,
            itemWithIssue: types.union(types.literal("anotherValue"), Model)
        })

        interface IModel extends Instance<typeof Model> {}

        interface FunctionArgs {
            model1: IModel
            model2: IModel
        }

        const store = Store.create({
            itemWithoutIssue: { foo: "works" },
            itemWithIssue: { foo: "has ts error in a regression" }
        })

        const f = (props: FunctionArgs) => {}

        const itemWithoutIssueModel = store.itemWithoutIssue
        const itemWithIssueModel =
            store.itemWithIssue === "anotherValue" ? null : store.itemWithIssue
        itemWithIssueModel && f({ model1: itemWithoutIssueModel, model2: itemWithIssueModel })
    })
})


================================================
FILE: __tests__/core/1664.test.ts
================================================
import { types as t } from "../../src/index"
import { describe, test } from "bun:test"

describe("1664. Array and model types are not inferred correctly when broken down into their components", () => {
    test("should not throw a typescript error", () => {
        // Simple concrete type with a creation type different than its instance type
        const date = t.custom<string, Date>({
            name: "Date",
            fromSnapshot: snapshot => new Date(snapshot),
            toSnapshot: dt => dt.toISOString(),
            isTargetType: (val: unknown) => val instanceof Date,
            getValidationMessage: (snapshot: unknown) =>
                typeof snapshot !== "string" || isNaN(Date.parse(snapshot))
                    ? `${snapshot} is not a valid Date string`
                    : ""
        })

        //Wrap the date type in an array type. IArrayType is a sub-interface of IType.
        const DateArray = t.array(date)

        //Pass the array type to t.union, which infers the component types as <C, S, T>
        const LoadableDateArray = t.union(t.literal("loading"), DateArray)

        //Instantiate the type
        const lda = LoadableDateArray.create([])

        //Try to use the array type as an instance
        if (lda !== "loading") {
            //Error: type of lda is essentially `(string | Date)[] | undefined`
            //The creation type has been mixed together with the instance type
            const dateArray: Date[] = lda
        }
    })
})


================================================
FILE: __tests__/core/2230.test.ts
================================================
//github.com/mobxjs/mobx-state-tree/issues/2230
import { describe, test } from "bun:test"
import { types, Instance } from "../../src/index"

describe("2230 - type instantiation is excessively deep and possibly infinite", () => {
    test("does not happen", () => {
        const ModelProps = types
            .model({
                prop01: "",
                prop02: "",
                prop03: ""
            })
            .props({
                prop11: "",
                prop12: "",
                prop13: ""
            })
            .props({
                prop21: "",
                prop22: "",
                prop23: ""
            })
            .props({
                prop31: "",
                prop32: "",
                prop33: ""
            })
            .props({
                prop41: "",
                prop42: "",
                prop43: ""
            })
            .props({
                prop51: "",
                prop52: "",
                prop53: ""
            })
            .props({
                prop61: "",
                prop62: "",
                prop63: ""
            })
            .props({
                prop71: "",
                prop72: "",
                prop73: ""
            })
            .props({
                prop81: "",
                prop82: "",
                prop83: ""
            })
            .props({
                prop91: "",
                prop92: "",
                prop93: ""
            })
        interface IModelProps extends Instance<typeof ModelProps> {}

        const ModelVolatile = ModelProps.volatile(() => ({
            vol01: null,
            vol02: null,
            vol03: null
        }))
            .volatile(() => ({
                vol11: null,
                vol12: null,
                vol13: null
            }))
            .volatile(() => ({
                vol21: null,
                vol22: null,
                vol23: null
            }))
            .volatile(() => ({
                vol31: null,
                vol32: null,
                vol33: null
            }))
            .volatile(() => ({
                vol41: null,
                vol42: null,
                vol43: null
            }))
            .volatile(() => ({
                vol51: null,
                vol52: null,
                vol53: null
            }))
            .volatile(() => ({
                vol61: null,
                vol62: null,
                vol63: null
            }))
            .volatile(() => ({
                vol71: null,
                vol72: null,
                vol73: null
            }))
            .volatile(() => ({
                vol81: null,
                vol82: null,
                vol83: null
            }))
            .volatile(() => ({
                vol91: null,
                vol92: null,
                vol93: null
            }))
        interface IModelVolatile extends Instance<typeof ModelVolatile> {}

        const ModelViews = ModelVolatile.views((self: IModelVolatile) => ({
            get vol01Var() {
                return self.vol01
            }
        }))
        interface IModelViews extends Instance<typeof ModelViews> {}

        const Action1 = ModelViews.actions((self: IModelViews) => ({
            getProp01(): string {
                return self.prop01
            }
        }))
        interface IAction1 extends Instance<typeof Action1> {}

        const Action2 = Action1.actions((self: IAction1) => ({
            getProp11(): string {
                return self.prop11
            }
        }))
        interface IAction2 extends Instance<typeof Action2> {}

        const Action3 = Action2.actions((self: IAction2) => ({
            getProp21(): string {
                return self.prop21
            }
        }))
        interface IAction3 extends Instance<typeof Action3> {}

        const Action4 = Action3.actions((self: IAction3) => ({
            getProp31(): string {
                return self.prop31
            }
        }))
        interface IAction4 extends Instance<typeof Action4> {}

        const Action5 = Action4.actions((self: IAction4) => ({
            getProp41(): string {
                return self.prop41
            }
        }))
            .actions((self: IAction4) => ({
                getProp51(): string {
                    return self.prop51
                }
            }))
            .actions((self: IAction4) => ({
                getProp61(): string {
                    return self.prop61
                }
            }))
            .actions((self: IAction4) => ({
                getProp71(): string {
                    return self.prop71
                }
            }))
            .actions((self: IAction4) => ({
                getProp81(): string {
                    return self.prop81
                }
            }))
            .actions((self: IAction4) => ({
                getProp91(): string {
                    return self.prop91
                }
            }))
        interface IAction5 extends Instance<typeof Action5> {}
    })
})


================================================
FILE: __tests__/core/__snapshots__/async.test.ts.snap
================================================
// Bun Snapshot v1, https://goo.gl/fbAQLP

exports[`can handle erroring actions 1`] = `
[
  {
    "allParentIds": [],
    "args": [
      "black",
    ],
    "id": 1,
    "name": "startFetch",
    "parentActionEvent": undefined,
    "parentEvent": undefined,
    "parentId": 0,
    "rootId": 1,
    "type": "action",
  },
  {
    "allParentIds": [
      1,
    ],
    "args": [
      "black",
    ],
    "id": 2,
    "name": "fetchData",
    "parentActionEvent": {
      "allParentIds": [],
      "args": [
        "black",
      ],
      "id": 1,
      "name": "startFetch",
      "parentActionEvent": undefined,
      "parentEvent": undefined,
      "parentId": 0,
      "rootId": 1,
      "type": "action",
    },
    "parentEvent": {
      "allParentIds": [],
      "args": [
        "black",
      ],
      "id": 1,
      "name": "startFetch",
      "parentActionEvent": undefined,
      "parentEvent": undefined,
      "parentId": 0,
      "rootId": 1,
      "type": "action",
    },
    "parentId": 1,
    "rootId": 1,
    "type": "flow_spawn",
  },
  {
    "allParentIds": [
      1,
    ],
    "args": [
      undefined,
    ],
    "id": 2,
    "name": "fetchData",
    "parentActionEvent": {
      "allParentIds": [],
      "args": [
        "black",
      ],
      "id": 1,
      "name": "startFetch",
      "parentActionEvent": undefined,
      "parentEvent": undefined,
      "parentId": 0,
      "rootId": 1,
      "type": "action",
    },
    "parentEvent": {
      "allParentIds": [],
      "args": [
        "black",
      ],
      "id": 1,
      "name": "startFetch",
      "parentActionEvent": undefined,
      "parentEvent": undefined,
      "parentId": 0,
      "rootId": 1,
      "type": "action",
    },
    "parentId": 1,
    "rootId": 1,
    "type": "flow_resume",
  },
  {
    "allParentIds": [
      1,
    ],
    "args": [
      "black",
    ],
    "id": 2,
    "name": "fetchData",
    "parentActionEvent": {
      "allParentIds": [],
      "args": [
        "black",
      ],
      "id": 1,
      "name": "startFetch",
      "parentActionEvent": undefined,
      "parentEvent": undefined,
      "parentId": 0,
      "rootId": 1,
      "type": "action",
    },
    "parentEvent": {
      "allParentIds": [],
      "args": [
        "black",
      ],
      "id": 1,
      "name": "startFetch",
      "parentActionEvent": undefined,
      "parentEvent": undefined,
      "parentId": 0,
      "rootId": 1,
      "type": "action",
    },
    "parentId": 1,
    "rootId": 1,
    "type": "flow_throw",
  },
]
`;

exports[`empty sequence works 1`] = `
[
  {
    "allParentIds": [],
    "args": [
      "black",
    ],
    "id": 1,
    "name": "startFetch",
    "parentActionEvent": undefined,
    "parentEvent": undefined,
    "parentId": 0,
    "rootId": 1,
    "type": "action",
  },
  {
    "allParentIds": [
      1,
    ],
    "args": [
      "black",
    ],
    "id": 2,
    "name": "fetchData",
    "parentActionEvent": {
      "allParentIds": [],
      "args": [
        "black",
      ],
      "id": 1,
      "name": "startFetch",
      "parentActionEvent": undefined,
      "parentEvent": undefined,
      "parentId": 0,
      "rootId": 1,
      "type": "action",
    },
    "parentEvent": {
      "allParentIds": [],
      "args": [
        "black",
      ],
      "id": 1,
      "name": "startFetch",
      "parentActionEvent": undefined,
      "parentEvent": undefined,
      "parentId": 0,
      "rootId": 1,
      "type": "action",
    },
    "parentId": 1,
    "rootId": 1,
    "type": "flow_spawn",
  },
  {
    "allParentIds": [
      1,
    ],
    "args": [
      undefined,
    ],
    "id": 2,
    "name": "fetchData",
    "parentActionEvent": {
      "allParentIds": [],
      "args": [
        "black",
      ],
      "id": 1,
      "name": "startFetch",
      "parentActionEvent": undefined,
      "parentEvent": undefined,
      "parentId": 0,
      "rootId": 1,
      "type": "action",
    },
    "parentEvent": {
      "allParentIds": [],
      "args": [
        "black",
      ],
      "id": 1,
      "name": "startFetch",
      "parentActionEvent": undefined,
      "parentEvent": undefined,
      "parentId": 0,
      "rootId": 1,
      "type": "action",
    },
    "parentId": 1,
    "rootId": 1,
    "type": "flow_resume",
  },
  {
    "allParentIds": [
      1,
    ],
    "args": [
      undefined,
    ],
    "id": 2,
    "name": "fetchData",
    "parentActionEvent": {
      "allParentIds": [],
      "args": [
        "black",
      ],
      "id": 1,
      "name": "startFetch",
      "parentActionEvent": undefined,
      "parentEvent": undefined,
      "parentId": 0,
      "rootId": 1,
      "type": "action",
    },
    "parentEvent": {
      "allParentIds": [],
      "args": [
        "black",
      ],
      "id": 1,
      "name": "startFetch",
      "parentActionEvent": undefined,
      "parentEvent": undefined,
      "parentId": 0,
      "rootId": 1,
      "type": "action",
    },
    "parentId": 1,
    "rootId": 1,
    "type": "flow_return",
  },
]
`;

exports[`typings 1`] = `
[
  {
    "allParentIds": [],
    "args": [
      "black",
    ],
    "id": 1,
    "name": "startFetch",
    "parentActionEvent": undefined,
    "parentEvent": undefined,
    "parentId": 0,
    "rootId": 1,
    "type": "action",
  },
  {
    "allParentIds": [
      1,
    ],
    "args": [
      "black",
    ],
    "id": 2,
    "name": "fetchData",
    "parentActionEvent": {
      "allParentIds": [],
      "args": [
        "black",
      ],
      "id": 1,
      "name": "startFetch",
      "parentActionEvent": undefined,
      "parentEvent": undefined,
      "parentId": 0,
      "rootId": 1,
      "type": "action",
    },
    "parentEvent": {
      "allParentIds": [],
      "args": [
        "black",
      ],
      "id": 1,
      "name": "startFetch",
      "parentActionEvent": undefined,
      "parentEvent": undefined,
      "parentId": 0,
      "rootId": 1,
      "type": "action",
    },
    "parentId": 1,
    "rootId": 1,
    "type": "flow_spawn",
  },
  {
    "allParentIds": [
      1,
    ],
    "args": [
      undefined,
    ],
    "id": 2,
    "name": "fetchData",
    "parentActionEvent": {
      "allParentIds": [],
      "args": [
        "black",
      ],
      "id": 1,
      "name": "startFetch",
      "parentActionEvent": undefined,
      "parentEvent": undefined,
      "parentId": 0,
      "rootId": 1,
      "type": "action",
    },
    "parentEvent": {
      "allParentIds": [],
      "args": [
        "black",
      ],
      "id": 1,
      "name": "startFetch",
      "parentActionEvent": undefined,
      "parentEvent": undefined,
      "parentId": 0,
      "rootId": 1,
      "type": "action",
    },
    "parentId": 1,
    "rootId": 1,
    "type": "flow_resume",
  },
  {
    "allParentIds": [
      1,
    ],
    "args": [
      "tea",
    ],
    "id": 2,
    "name": "fetchData",
    "parentActionEvent": {
      "allParentIds": [],
      "args": [
        "black",
      ],
      "id": 1,
      "name": "startFetch",
      "parentActionEvent": undefined,
      "parentEvent": undefined,
      "parentId": 0,
      "rootId": 1,
      "type": "action",
    },
    "parentEvent": {
      "allParentIds": [],
      "args": [
        "black",
      ],
      "id": 1,
      "name": "startFetch",
      "parentActionEvent": undefined,
      "parentEvent": undefined,
      "parentId": 0,
      "rootId": 1,
      "type": "action",
    },
    "parentId": 1,
    "rootId": 1,
    "type": "flow_resume_error",
  },
  {
    "allParentIds": [
      1,
    ],
    "args": [
      "biscuit",
    ],
    "id": 2,
    "name": "fetchData",
    "parentActionEvent": {
      "allParentIds": [],
      "args": [
        "black",
      ],
      "id": 1,
      "name": "startFetch",
      "parentActionEvent": undefined,
      "parentEvent": undefined,
      "parentId": 0,
      "rootId": 1,
      "type": "action",
    },
    "parentEvent": {
      "allParentIds": [],
      "args": [
        "black",
      ],
      "id": 1,
      "name": "startFetch",
      "parentActionEvent": undefined,
      "parentEvent": undefined,
      "parentId": 0,
      "rootId": 1,
      "type": "action",
    },
    "parentId": 1,
    "rootId": 1,
    "type": "flow_return",
  },
]
`;

exports[`typings 2`] = `
[
  {
    "allParentIds": [],
    "args": [
      "black",
    ],
    "id": 1,
    "name": "startFetch",
    "parentActionEvent": undefined,
    "parentEvent": undefined,
    "parentId": 0,
    "rootId": 1,
    "type": "action",
  },
  {
    "allParentIds": [
      1,
    ],
    "args": [
      "black",
    ],
    "id": 2,
    "name": "fetchData",
    "parentActionEvent": {
      "allParentIds": [],
      "args": [
        "black",
      ],
      "id": 1,
      "name": "startFetch",
      "parentActionEvent": undefined,
      "parentEvent": undefined,
      "parentId": 0,
      "rootId": 1,
      "type": "action",
    },
    "parentEvent": {
      "allParentIds": [],
      "args": [
        "black",
      ],
      "id": 1,
      "name": "startFetch",
      "parentActionEvent": undefined,
      "parentEvent": undefined,
      "parentId": 0,
      "rootId": 1,
      "type": "action",
    },
    "parentId": 1,
    "rootId": 1,
    "type": "flow_spawn",
  },
  {
    "allParentIds": [
      1,
    ],
    "args": [
      undefined,
    ],
    "id": 2,
    "name": "fetchData",
    "parentActionEvent": {
      "allParentIds": [],
      "args": [
        "black",
      ],
      "id": 1,
      "name": "startFetch",
      "parentActionEvent": undefined,
      "parentEvent": undefined,
      "parentId": 0,
      "rootId": 1,
      "type": "action",
    },
    "parentEvent": {
      "allParentIds": [],
      "args": [
        "black",
      ],
      "id": 1,
      "name": "startFetch",
      "parentActionEvent": undefined,
      "parentEvent": undefined,
      "parentId": 0,
      "rootId": 1,
      "type": "action",
    },
    "parentId": 1,
    "rootId": 1,
    "type": "flow_resume",
  },
  {
    "allParentIds": [
      1,
    ],
    "args": [
      "x",
    ],
    "id": 2,
    "name": "fetchData",
    "parentActionEvent": {
      "allParentIds": [],
      "args": [
        "black",
      ],
      "id": 1,
      "name": "startFetch",
      "parentActionEvent": undefined,
      "parentEvent": undefined,
      "parentId": 0,
      "rootId": 1,
      "type": "action",
    },
    "parentEvent": {
      "allParentIds": [],
      "args": [
        "black",
      ],
      "id": 1,
      "name": "startFetch",
      "parentActionEvent": undefined,
      "parentEvent": undefined,
      "parentId": 0,
      "rootId": 1,
      "type": "action",
    },
    "parentId": 1,
    "rootId": 1,
    "type": "flow_resume_error",
  },
  {
    "allParentIds": [
      1,
    ],
    "args": [
      "x",
    ],
    "id": 2,
    "name": "fetchData",
    "parentActionEvent": {
      "allParentIds": [],
      "args": [
        "black",
      ],
      "id": 1,
      "name": "startFetch",
      "parentActionEvent": undefined,
      "parentEvent": undefined,
      "parentId": 0,
      "rootId": 1,
      "type": "action",
    },
    "parentEvent": {
      "allParentIds": [],
      "args": [
        "black",
      ],
      "id": 1,
      "name": "startFetch",
      "parentActionEvent": undefined,
      "parentEvent": undefined,
      "parentId": 0,
      "rootId": 1,
      "type": "action",
    },
    "parentId": 1,
    "rootId": 1,
    "type": "flow_throw",
  },
]
`;

exports[`can handle nested async actions when using decorate 1`] = `
[
  {
    "allParentIds": [],
    "args": [
      "black",
    ],
    "id": 1,
    "name": "startFetch",
    "parentActionEvent": undefined,
    "parentEvent": undefined,
    "parentId": 0,
    "rootId": 1,
    "type": "action",
  },
  {
    "allParentIds": [
      1,
    ],
    "args": [
      "black",
    ],
    "id": 2,
    "name": "fetchData",
    "parentActionEvent": {
      "allParentIds": [],
      "args": [
        "black",
      ],
      "id": 1,
      "name": "startFetch",
      "parentActionEvent": undefined,
      "parentEvent": undefined,
      "parentId": 0,
      "rootId": 1,
      "type": "action",
    },
    "parentEvent": {
      "allParentIds": [],
      "args": [
        "black",
      ],
      "id": 1,
      "name": "startFetch",
      "parentActionEvent": undefined,
      "parentEvent": undefined,
      "parentId": 0,
      "rootId": 1,
      "type": "action",
    },
    "parentId": 1,
    "rootId": 1,
    "type": "flow_spawn",
  },
  {
    "allParentIds": [
      1,
    ],
    "args": [
      undefined,
    ],
    "id": 2,
    "name": "fetchData",
    "parentActionEvent": {
      "allParentIds": [],
      "args": [
        "black",
      ],
      "id": 1,
      "name": "startFetch",
      "parentActionEvent": undefined,
      "parentEvent": undefined,
      "parentId": 0,
      "rootId": 1,
      "type": "action",
    },
    "parentEvent": {
      "allParentIds": [],
      "args": [
        "black",
      ],
      "id": 1,
      "name": "startFetch",
      "parentActionEvent": undefined,
      "parentEvent": undefined,
      "parentId": 0,
      "rootId": 1,
      "type": "action",
    },
    "parentId": 1,
    "rootId": 1,
    "type": "flow_resume",
  },
  {
    "allParentIds": [
      1,
    ],
    "args": [
      "drinking coffee",
    ],
    "id": 2,
    "name": "fetchData",
    "parentActionEvent": {
      "allParentIds": [],
      "args": [
        "black",
      ],
      "id": 1,
      "name": "startFetch",
      "parentActionEvent": undefined,
      "parentEvent": undefined,
      "parentId": 0,
      "rootId": 1,
      "type": "action",
    },
    "parentEvent": {
      "allParentIds": [],
      "args": [
        "black",
      ],
      "id": 1,
      "name": "startFetch",
      "parentActionEvent": undefined,
      "parentEvent": undefined,
      "parentId": 0,
      "rootId": 1,
      "type": "action",
    },
    "parentId": 1,
    "rootId": 1,
    "type": "flow_resume",
  },
  {
    "allParentIds": [
      1,
    ],
    "args": [
      "awake",
    ],
    "id": 2,
    "name": "fetchData",
    "parentActionEvent": {
      "allParentIds": [],
      "args": [
        "black",
      ],
      "id": 1,
      "name": "startFetch",
      "parentActionEvent": undefined,
      "parentEvent": undefined,
      "parentId": 0,
      "rootId": 1,
      "type": "action",
    },
    "parentEvent": {
      "allParentIds": [],
      "args": [
        "black",
      ],
      "id": 1,
      "name": "startFetch",
      "parentActionEvent": undefined,
      "parentEvent": undefined,
      "parentId": 0,
      "rootId": 1,
      "type": "action",
    },
    "parentId": 1,
    "rootId": 1,
    "type": "flow_return",
  },
]
`;

exports[`can handle nested async actions when using decorate 2`] = `
[
  {
    "allParentIds": [],
    "args": [
      "black",
    ],
    "id": 1,
    "name": "startFetch",
    "parentActionEvent": undefined,
    "parentEvent": undefined,
    "parentId": 0,
    "rootId": 1,
    "type": "action",
  },
  {
    "allParentIds": [
      1,
    ],
    "args": [
      "black",
    ],
    "id": 2,
    "name": "fetchData",
    "parentActionEvent": {
      "allParentIds": [],
      "args": [
        "black",
      ],
      "id": 1,
      "name": "startFetch",
      "parentActionEvent": undefined,
      "parentEvent": undefined,
      "parentId": 0,
      "rootId": 1,
      "type": "action",
    },
    "parentEvent": {
      "allParentIds": [],
      "args": [
        "black",
      ],
      "id": 1,
      "name": "startFetch",
      "parentActionEvent": undefined,
      "parentEvent": undefined,
      "parentId": 0,
      "rootId": 1,
      "type": "action",
    },
    "parentId": 1,
    "rootId": 1,
    "type": "flow_spawn",
  },
  {
    "allParentIds": [
      1,
    ],
    "args": [
      undefined,
    ],
    "id": 2,
    "name": "fetchData",
    "parentActionEvent": {
      "allParentIds": [],
      "args": [
        "black",
      ],
      "id": 1,
      "name": "startFetch",
      "parentActionEvent": undefined,
      "parentEvent": undefined,
      "parentId": 0,
      "rootId": 1,
      "type": "action",
    },
    "parentEvent": {
      "allParentIds": [],
      "args": [
        "black",
      ],
      "id": 1,
      "name": "startFetch",
      "parentActionEvent": undefined,
      "parentEvent": undefined,
      "parentId": 0,
      "rootId": 1,
      "type": "action",
    },
    "parentId": 1,
    "rootId": 1,
    "type": "flow_resume",
  },
  {
    "allParentIds": [
      1,
      2,
    ],
    "args": [
      "drinking black",
    ],
    "id": 3,
    "name": "uppercase",
    "parentActionEvent": {
      "allParentIds": [],
      "args": [
        "black",
      ],
      "id": 1,
      "name": "startFetch",
      "parentActionEvent": undefined,
      "parentEvent": undefined,
      "parentId": 0,
      "rootId": 1,
      "type": "action",
    },
    "parentEvent": {
      "allParentIds": [
        1,
      ],
      "args": [
        undefined,
      ],
      "id": 2,
      "name": "fetchData",
      "parentActionEvent": {
        "allParentIds": [],
        "args": [
          "black",
        ],
        "id": 1,
        "name": "startFetch",
        "parentActionEvent": undefined,
        "parentEvent": undefined,
        "parentId": 0,
        "rootId": 1,
        "type": "action",
      },
      "parentEvent": {
        "allParentIds": [],
        "args": [
          "black",
        ],
        "id": 1,
        "name": "startFetch",
        "parentActionEvent": undefined,
        "parentEvent": undefined,
        "parentId": 0,
        "rootId": 1,
        "type": "action",
      },
      "parentId": 1,
      "rootId": 1,
      "type": "flow_resume",
    },
    "parentId": 2,
    "rootId": 1,
    "type": "flow_spawn",
  },
  {
    "allParentIds": [
      1,
      2,
    ],
    "args": [
      undefined,
    ],
    "id": 3,
    "name": "uppercase",
    "parentActionEvent": {
      "allParentIds": [],
      "args": [
        "black",
      ],
      "id": 1,
      "name": "startFetch",
      "parentActionEvent": undefined,
      "parentEvent": undefined,
      "parentId": 0,
      "rootId": 1,
      "type": "action",
    },
    "parentEvent": {
      "allParentIds": [
        1,
      ],
      "args": [
        undefined,
      ],
      "id": 2,
      "name": "fetchData",
      "parentActionEvent": {
        "allParentIds": [],
        "args": [
          "black",
        ],
        "id": 1,
        "name": "startFetch",
        "parentActionEvent": undefined,
        "parentEvent": undefined,
        "parentId": 0,
        "rootId": 1,
        "type": "action",
      },
      "parentEvent": {
        "allParentIds": [],
        "args": [
          "black",
        ],
        "id": 1,
        "name": "startFetch",
        "parentActionEvent": undefined,
        "parentEvent": undefined,
        "parentId": 0,
        "rootId": 1,
        "type": "action",
      },
      "parentId": 1,
      "rootId": 1,
      "type": "flow_resume",
    },
    "parentId": 2,
    "rootId": 1,
    "type": "flow_resume",
  },
  {
    "allParentIds": [
      1,
      2,
    ],
    "args": [
      "DRINKING BLACK",
    ],
    "id": 3,
    "name": "uppercase",
    "parentActionEvent": {
      "allParentIds": [],
      "args": [
        "black",
      ],
      "id": 1,
      "name": "startFetch",
      "parentActionEvent": undefined,
      "parentEvent": undefined,
      "parentId": 0,
      "rootId": 1,
      "type": "action",
    },
    "parentEvent": {
      "allParentIds": [
        1,
      ],
      "args": [
        undefined,
      ],
      "id": 2,
      "name": "fetchData",
      "parentActionEvent": {
        "allParentIds": [],
        "args": [
          "black",
        ],
        "id": 1,
        "name": "startFetch",
        "parentActionEvent": undefined,
        "parentEvent": undefined,
        "parentId": 0,
        "rootId": 1,
        "type": "action",
      },
      "parentEvent": {
        "allParentIds": [],
        "args": [
          "black",
        ],
        "id": 1,
        "name": "startFetch",
        "parentActionEvent": undefined,
        "parentEvent": undefined,
        "parentId": 0,
        "rootId": 1,
        "type": "action",
      },
      "parentId": 1,
      "rootId": 1,
      "type": "flow_resume",
    },
    "parentId": 2,
    "rootId": 1,
    "type": "flow_resume",
  },
  {
    "allParentIds": [
      1,
      2,
    ],
    "args": [
      "DRINKING BLACK",
    ],
    "id": 3,
    "name": "uppercase",
    "parentActionEvent": {
      "allParentIds": [],
      "args": [
        "black",
      ],
      "id": 1,
      "name": "startFetch",
      "parentActionEvent": undefined,
      "parentEvent": undefined,
      "parentId": 0,
      "rootId": 1,
      "type": "action",
    },
    "parentEvent": {
      "allParentIds": [
        1,
      ],
      "args": [
        undefined,
      ],
      "id": 2,
      "name": "fetchData",
      "parentActionEvent": {
        "allParentIds": [],
        "args": [
          "black",
        ],
        "id": 1,
        "name": "startFetch",
        "parentActionEvent": undefined,
        "parentEvent": undefined,
        "parentId": 0,
        "rootId": 1,
        "type": "action",
      },
      "parentEvent": {
        "allParentIds": [],
        "args": [
          "black",
        ],
        "id": 1,
        "name": "startFetch",
        "parentActionEvent": undefined,
        "parentEvent": undefined,
        "parentId": 0,
        "rootId": 1,
        "type": "action",
      },
      "parentId": 1,
      "rootId": 1,
      "type": "flow_resume",
    },
    "parentId": 2,
    "rootId": 1,
    "type": "flow_return",
  },
  {
    "allParentIds": [
      1,
    ],
    "args": [
      "DRINKING BLACK",
    ],
    "id": 2,
    "name": "fetchData",
    "parentActionEvent": {
      "allParentIds": [],
      "args": [
        "black",
      ],
      "id": 1,
      "name": "startFetch",
      "parentActionEvent": undefined,
      "parentEvent": undefined,
      "parentId": 0,
      "rootId": 1,
      "type": "action",
    },
    "parentEvent": {
      "allParentIds": [],
      "args": [
        "black",
      ],
      "id": 1,
      "name": "startFetch",
      "parentActionEvent": undefined,
      "parentEvent": undefined,
      "parentId": 0,
      "rootId": 1,
      "type": "action",
    },
    "parentId": 1,
    "rootId": 1,
    "type": "flow_resume",
  },
  {
    "allParentIds": [
      1,
    ],
    "args": [
      "DRINKING BLACK",
    ],
    "id": 2,
    "name": "fetchData",
    "parentActionEvent": {
      "allParentIds": [],
      "args": [
        "black",
      ],
      "id": 1,
      "name": "startFetch",
      "parentActionEvent": undefined,
      "parentEvent": undefined,
      "parentId": 0,
      "rootId": 1,
      "type": "action",
    },
    "parentEvent": {
      "allParentIds": [],
      "args": [
        "black",
      ],
      "id": 1,
      "name": "startFetch",
      "parentActionEvent": undefined,
      "parentEvent": undefined,
      "parentId": 0,
      "rootId": 1,
      "type": "action",
    },
    "parentId": 1,
    "rootId": 1,
    "type": "flow_return",
  },
]
`;


================================================
FILE: __tests__/core/__snapshots__/custom-type.test.ts.snap
================================================
// Bun Snapshot v1, https://goo.gl/fbAQLP

exports[`reassignments will work 1`] = `
[
  {
    "balance": "2.5",
    "lastTransaction": null,
  },
  {
    "balance": "3.5",
    "lastTransaction": null,
  },
  {
    "balance": "4.5",
    "lastTransaction": null,
  },
  {
    "balance": "4.5",
    "lastTransaction": "2.5",
  },
  {
    "balance": "4.5",
    "lastTransaction": null,
  },
]
`;

exports[`reassignments will work 2`] = `
[
  {
    "op": "replace",
    "path": "/balance",
    "value": "2.5",
  },
  {
    "op": "replace",
    "path": "/balance",
    "value": "3.5",
  },
  {
    "op": "replace",
    "path": "/balance",
    "value": "4.5",
  },
  {
    "op": "replace",
    "path": "/lastTransaction",
    "value": "2.5",
  },
  {
    "op": "replace",
    "path": "/lastTransaction",
    "value": null,
  },
]
`;

exports[`complex reassignments will work 1`] = `
[
  {
    "balance": [
      2,
      5,
    ],
  },
  {
    "balance": [
      2,
      5,
    ],
  },
  {
    "balance": [
      3,
      5,
    ],
  },
  {
    "balance": [
      4,
      5,
    ],
  },
]
`;

exports[`complex reassignments will work 2`] = `
[
  {
    "op": "replace",
    "path": "/balance",
    "value": [
      2,
      5,
    ],
  },
  {
    "op": "replace",
    "path": "/balance",
    "value": [
      2,
      5,
    ],
  },
  {
    "op": "replace",
    "path": "/balance",
    "value": [
      3,
      5,
    ],
  },
  {
    "op": "replace",
    "path": "/balance",
    "value": [
      4,
      5,
    ],
  },
]
`;


================================================
FILE: __tests__/core/__snapshots__/reference-custom.test.ts.snap
================================================
// Bun Snapshot v1, https://goo.gl/fbAQLP

exports[`it should support custom references - adv 1`] = `
[
  "1",
  "2",
  "1",
  null,
  "3",
]
`;

exports[`it should support custom references - adv 2`] = `
[
  {
    "selection": "Michel",
    "users": {
      "1": {
        "id": "1",
        "name": "Michel",
      },
      "2": {
        "id": "2",
        "name": "Mattia",
      },
    },
  },
  {
    "selection": "Mattia",
    "users": {
      "1": {
        "id": "1",
        "name": "Michel",
      },
      "2": {
        "id": "2",
        "name": "Mattia",
      },
    },
  },
  {
    "selection": "Michel",
    "users": {
      "1": {
        "id": "1",
        "name": "Michel",
      },
      "2": {
        "id": "2",
        "name": "Mattia",
      },
    },
  },
  {
    "selection": "Michel",
    "users": {
      "2": {
        "id": "2",
        "name": "Mattia",
      },
    },
  },
  {
    "selection": "Michel",
    "users": {
      "2": {
        "id": "2",
        "name": "Mattia",
      },
      "3": {
        "id": "3",
        "name": "Michel",
      },
    },
  },
]
`;

exports[`it should support custom references - adv 3`] = `
[
  {
    "op": "replace",
    "path": "/selection",
    "value": "Michel",
  },
  {
    "op": "replace",
    "path": "/selection",
    "value": "Mattia",
  },
  {
    "op": "replace",
    "path": "/selection",
    "value": "Michel",
  },
  {
    "op": "remove",
    "path": "/users/1",
  },
  {
    "op": "add",
    "path": "/users/3",
    "value": {
      "id": "3",
      "name": "Michel",
    },
  },
]
`;

exports[`it should support custom references - adv 4`] = `
[
  {
    "op": "replace",
    "path": "/selection",
    "value": "Mattia",
  },
  {
    "op": "replace",
    "path": "/selection",
    "value": "Michel",
  },
  {
    "op": "replace",
    "path": "/selection",
    "value": "Mattia",
  },
  {
    "op": "add",
    "path": "/users/1",
    "value": {
      "id": "1",
      "name": "Michel",
    },
  },
  {
    "op": "remove",
    "path": "/users/3",
  },
]
`;


================================================
FILE: __tests__/core/action.test.ts
================================================
import { configure } from "mobx"
import {
    recordActions,
    types,
    getSnapshot,
    onAction,
    applyPatch,
    applySnapshot,
    addMiddleware,
    getRoot,
    cast,
    IMiddlewareEvent,
    ISerializedActionCall,
    Instance
} from "../../src"
import { expect, test } from "bun:test"

/// Simple action replay and invocation
const Task = types
    .model({
        done: false
    })
    .actions(self => {
        function toggle() {
            self.done = !self.done
            return self.done
        }
        return {
            toggle
        }
    })
test("it should be possible to invoke a simple action", () => {
    const t1 = Task.create()
    expect(t1.done).toBe(false)
    expect(t1.toggle()).toBe(true)
    expect(t1.done).toBe(true)
})
test("it should be possible to record & replay a simple action", () => {
    const t1 = Task.create()
    const t2 = Task.create()
    expect(t1.done).toBe(false)
    expect(t2.done).toBe(false)
    const recorder = recordActions(t1)
    t1.toggle()
    t1.toggle()
    t1.toggle()
    expect(recorder.actions).toEqual([
        { name: "toggle", path: "", args: [] },
        { name: "toggle", path: "", args: [] },
        { name: "toggle", path: "", args: [] }
    ])
    recorder.replay(t2)
    expect(t2.done).toBe(true)
})
test("applying patches should be recordable and replayable", () => {
    const t1 = Task.create()
    const t2 = Task.create()
    const recorder = recordActions(t1)
    expect(t1.done).toBe(false)
    applyPatch(t1, { op: "replace", path: "/done", value: true })
    expect(t1.done).toBe(true)
    expect(recorder.actions).toEqual([
        {
            name: "@APPLY_PATCHES",
            path: "",
            args: [[{ op: "replace", path: "/done", value: true }]]
        }
    ])
    recorder.replay(t2)
    expect(t2.done).toBe(true)
})
test("applying patches should be replacing the root store", () => {
    const t1 = Task.create()
    const recorder = recordActions(t1)
    expect(t1.done).toBe(false)
    applyPatch(t1, { op: "replace", path: "", value: { done: true } })
    expect(t1.done).toBe(true)
    expect(recorder.actions).toEqual([
        {
            name: "@APPLY_PATCHES",
            path: "",
            args: [[{ op: "replace", path: "", value: { done: true } }]]
        }
    ])
})
test("applying snapshots should be recordable and replayable", () => {
    const t1 = Task.create()
    const t2 = Task.create()
    const recorder = recordActions(t1)
    expect(t1.done).toBe(false)
    applySnapshot(t1, { done: true })
    expect(t1.done).toBe(true)
    expect(recorder.actions).toEqual([
        {
            name: "@APPLY_SNAPSHOT",
            path: "",
            args: [{ done: true }]
        }
    ])
    recorder.replay(t2)
    expect(t2.done).toBe(true)
})
// Complex actions
const Customer = types.model("Customer", {
    id: types.identifierNumber,
    name: types.string
})
const Order = types
    .model("Order", {
        customer: types.maybeNull(types.reference(Customer))
    })
    .actions(self => {
        function setCustomer(customer: Instance<typeof Customer>) {
            self.customer = customer
        }
        function noopSetCustomer(_: Instance<typeof Customer>) {
            // noop
        }
        return {
            setCustomer,
            noopSetCustomer
        }
    })
const OrderStore = types.model("OrderStore", {
    customers: types.array(Customer),
    orders: types.array(Order)
})
function createTestStore() {
    const store = OrderStore.create({
        customers: [{ id: 1, name: "Mattia" }],
        orders: [
            {
                customer: null
            }
        ]
    })
    onAction(store, () => {})
    return store
}
test("it should not be possible to pass a complex object", () => {
    const store = createTestStore()
    const recorder = recordActions(store)
    expect(store.customers[0].name).toBe("Mattia")
    store.orders[0].setCustomer(store.customers[0])
    expect(store.orders[0].customer!.name).toBe("Mattia")
    expect(store.orders[0].customer).toBe(store.customers[0])
    expect(getSnapshot(store)).toEqual({
        customers: [
            {
                id: 1,
                name: "Mattia"
            }
        ],
        orders: [
            {
                customer: 1
            }
        ]
    })
    expect(recorder.actions).toEqual([
        {
            name: "setCustomer",
            path: "/orders/0",
            args: [{ $MST_UNSERIALIZABLE: true, type: "[MSTNode: Customer]" }]
        }
    ])
})
if (process.env.NODE_ENV !== "production") {
    test("it should not be possible to set the wrong type", () => {
        const store = createTestStore()
        expect(() => {
            store.orders[0].setCustomer(store.orders[0] as any)
        }).toThrow(
            "Error while converting <Order@/orders/0> to `(reference(Customer) | null)`:\n\n    " +
                "value of type Order: <Order@/orders/0> is not assignable to type: `(reference(Customer) | null)`, expected an instance of `(reference(Customer) | null)` or a snapshot like `(reference(Customer) | null?)` instead."
        ) // wrong type!
    })
}
test("it should not be possible to pass the element of another tree", () => {
    const store1 = createTestStore()
    const store2 = createTestStore()
    const recorder = recordActions(store2)
    store2.orders[0].setCustomer(store1.customers[0])
    expect(recorder.actions).toEqual([
        {
            name: "setCustomer",
            path: "/orders/0",
            args: [
                {
                    $MST_UNSERIALIZABLE: true,
                    type: "[MSTNode: Customer]"
                }
            ]
        }
    ])
})
test("it should not be possible to pass an unserializable object", () => {
    const store = createTestStore()
    const circular = { a: null as any }
    circular.a = circular
    const recorder = recordActions(store)
    store.orders[0].noopSetCustomer(circular as any)
    store.orders[0].noopSetCustomer(Buffer.from("bla") as any)

    expect(recorder.actions).toEqual([
        {
            args: [
                {
                    $MST_UNSERIALIZABLE: true,
                    type: "TypeError: JSON.stringify cannot serialize cyclic structures."
                }
            ],
            name: "noopSetCustomer",
            path: "/orders/0"
        },
        {
            args: [
                {
                    $MST_UNSERIALIZABLE: true,
                    type: "[object Buffer]"
                }
            ],
            name: "noopSetCustomer",
            path: "/orders/0"
        }
    ])
})
test("it should be possible to pass a complex plain object", () => {
    const t1 = Task.create()
    const t2 = Task.create()
    const recorder = recordActions(t1)
    ;(t1 as any).toggle({ bla: ["nuff", ["said"]] }) // nonsense, but serializable!
    expect(recorder.actions).toEqual([
        { name: "toggle", path: "", args: [{ bla: ["nuff", ["said"]] }] }
    ])
    recorder.replay(t2)
    expect(t2.done).toBe(true)
})
test("action should be bound", () => {
    const task = Task.create()
    const f = task.toggle
    expect(f()).toBe(true)
    expect(task.done).toBe(true)
})
test("snapshot should be available and updated during an action", () => {
    const Model = types
        .model({
            x: types.number
        })
        .actions(self => {
            function inc() {
                self.x += 1
                const res = getSnapshot(self).x
                self.x += 1
                return res
            }
            return {
                inc
            }
        })
    const a = Model.create({ x: 2 })
    expect(a.inc()).toBe(3)
    expect(a.x).toBe(4)
    expect(getSnapshot(a).x).toBe(4)
})

test("indirectly called private functions should be able to modify state", () => {
    const Model = types
        .model({
            x: 3
        })
        .actions(self => {
            function incrementBy(delta: number) {
                self.x += delta
            }
            return {
                inc() {
                    incrementBy(1)
                },
                dec() {
                    incrementBy(-1)
                }
            }
        })
    const cnt = Model.create()
    expect(cnt.x).toBe(3)
    cnt.dec()
    expect(cnt.x).toBe(2)
    expect((cnt as any).incrementBy).toBe(undefined)
})
test("volatile state survives reonciliation", () => {
    const Model = types.model({ x: 3 }).actions(self => {
        let incrementor = 1
        return {
            setIncrementor(value: number) {
                incrementor = value
            },
            inc() {
                self.x += incrementor
            }
        }
    })
    const Store = types.model({
        cnt: types.optional(Model, {})
    })
    const store = Store.create()
    store.cnt.inc()
    expect(store.cnt.x).toBe(4)
    store.cnt.setIncrementor(3)
    store.cnt.inc()
    expect(store.cnt.x).toBe(7)
    applySnapshot(store, { cnt: { x: 2 } })
    expect(store.cnt.x).toBe(2)
    store.cnt.inc()
    expect(store.cnt.x).toBe(5) // incrementor was not lost
})
test("middleware events are correct", () => {
    configure({
        useProxies: "never"
    })

    const A = types.model({}).actions(self => ({
        a(x: number) {
            return this.b(x * 2)
        },
        b(y: number) {
            return y + 1
        }
    }))
    const a = A.create()
    const events: IMiddlewareEvent[] = []
    addMiddleware(a, function (call, next) {
        events.push(call)
        return next(call)
    })
    a.a(7)
    const event1 = {
        args: [7],
        context: {},
        id: 1,
        name: "a",
        parentId: 0,
        rootId: 1,
        allParentIds: [],
        tree: {},
        type: "action",
        parentEvent: undefined,
        parentActionEvent: undefined
    } as IMiddlewareEvent
    const event2 = {
        args: [14],
        context: {},
        id: 2,
        name: "b",
        parentId: 1,
        rootId: 1,
        allParentIds: [1],
        tree: {},
        type: "action",
        parentEvent: event1,
        parentActionEvent: event1
    } as IMiddlewareEvent
    expect(events).toEqual([event1, event2])
})

test("actions are mockable", () => {
    configure({
        useProxies: "never"
    })

    const M = types
        .model()
        .actions(self => ({
            method(): number {
                return 3
            }
        }))
        .views(self => ({
            view(): number {
                return 3
            }
        }))
    const m = M.create()
    if (process.env.NODE_ENV === "production") {
        expect(() => {
            m.method = function () {
                return 3
            }
        }).toThrow(TypeError)
        expect(() => {
            m.view = function () {
                return 3
            }
        }).toThrow(TypeError)
    } else {
        m.method = function () {
            return 4
        }
        expect(m.method()).toBe(4)
        m.view = function () {
            return 4
        }
        expect(m.view()).toBe(4)
    }
})

test("after attach action should work correctly", () => {
    const Todo = types
        .model({
            title: "test"
        })
        .actions(self => ({
            remove() {
                getRoot<typeof S>(self).remove(cast(self))
            }
        }))
    const S = types
        .model({
            todos: types.array(Todo)
        })
        .actions(self => ({
            remove(todo: Instance<typeof Todo>) {
                self.todos.remove(todo)
            }
        }))

    const s = S.create({
        todos: [{ title: "todo" }]
    })
    const events: ISerializedActionCall[] = []
    onAction(
        s,
        call => {
            events.push(call)
        },
        true
    )

    s.todos[0].remove()

    expect(events).toEqual([
        {
            args: [],
            name: "remove",
            path: "/todos/0"
        }
    ])
})


================================================
FILE: __tests__/core/actionTrackingMiddleware2.test.ts
================================================
import {
    addMiddleware,
    createActionTrackingMiddleware2,
    types,
    flow,
    IActionTrackingMiddleware2Call
} from "../../src"

import { expect, it, test } from "bun:test"

function createTestMiddleware(m: any, actionName: string, value: number, calls: string[]) {
    function checkCall(call: IActionTrackingMiddleware2Call<any>) {
        expect(call.name).toBe(actionName)
        expect(call.args).toEqual([value])
        expect(call.context).toBe(m)
        expect(call.env).toBe(call.id)
    }

    const mware = createActionTrackingMiddleware2({
        filter(call) {
            return call.name === actionName
        },
        onStart(call) {
            call.env = call.id // just to check env is copied properly down
            calls.push(`${call.name} (${call.id}) - onStart`)
            checkCall(call)
        },
        onFinish(call, error) {
            calls.push(`${call.name} (${call.id}) - onFinish (error: ${!!error})`)
            checkCall(call)
        }
    })

    addMiddleware(m, mware, false)
}

async function doTest(m: any, mode: "success" | "fail") {
    const calls: string[] = []

    createTestMiddleware(m, "setX", 10, calls)
    createTestMiddleware(m, "setY", 9, calls)

    try {
        await m.setZ(8) // -> setY(9) -> setX(10)
        if (mode === "fail") {
            expect().fail("should have failed")
        }
    } catch (e) {
        if (mode === "fail") {
            expect(e).toBe("error")
        } else {
            throw e
            // fail("should have succeeded")
        }
    }

    return calls
}

async function syncTest(mode: "success" | "fail") {
    const M = types
        .model({
            x: 1,
            y: 2,
            z: 3
        })
        .actions(self => ({
            setX(v: number) {
                self.x = v
                if (mode === "fail") {
                    throw "error"
                }
            },
            setY(v: number) {
                self.y = v
                this.setX(v + 1)
            },
            setZ(v: number) {
                self.z = v
                this.setY(v + 1)
            }
        }))

    const m = M.create()

    const calls = await doTest(m, mode)

    if (mode === "success") {
        expect(calls).toEqual([
            "setY (2) - onStart",
            "setX (3) - onStart",
            "setX (3) - onFinish (error: false)",
            "setY (2) - onFinish (error: false)"
        ])
    } else {
        expect(calls).toEqual([
            "setY (5) - onStart",
            "setX (6) - onStart",
            "setX (6) - onFinish (error: true)",
            "setY (5) - onFinish (error: true)"
        ])
    }
}

/**
 * This test checks that the middleware is called and
 */
test("sync action", async () => {
    await syncTest("success")
    await syncTest("fail")
})

async function flowTest(mode: "success" | "fail") {
    const _subFlow = flow(function* subFlow() {
        yield Promise.resolve()
    })

    const M = types
        .model({
            x: 1,
            y: 2,
            z: 3
        })
        .actions(self => ({
            setX: flow(function* flowSetX(v: number) {
                yield Promise.resolve()
                yield _subFlow()
                self.x = v
                if (mode === "fail") {
                    throw "error"
                }
            }),
            setY: flow(function* flowSetY(v: number) {
                self.y = v
                yield (self as any).setX(v + 1)
            }),
            setZ: flow(function* flowSetZ(v: number) {
                self.z = v
                yield (self as any).setY(v + 1)
            })
        }))

    const m = M.create()

    const calls = await doTest(m, mode)

    if (mode === "success") {
        expect(calls).toEqual([
            "setY (3) - onStart",
            "setX (5) - onStart",
            "setX (5) - onFinish (error: false)",
            "setY (3) - onFinish (error: false)"
        ])
    } else {
        expect(calls).toEqual([
            "setY (10) - onStart",
            "setX (12) - onStart",
            "setX (12) - onFinish (error: true)",
            "setY (10) - onFinish (error: true)"
        ])
    }
}

test("flow action", async () => {
    await flowTest("success")
    await flowTest("fail")
})

test("#1250", async () => {
    const M = types
        .model({
            x: 0,
            y: 0
        })
        .actions(self => ({
            setX: flow(function* () {
                self.x = 10
                yield new Promise(resolve => setTimeout(resolve, 10))
            }),
            setY() {
                self.y = 10
            }
        }))

    const calls: string[] = []
    const mware = createActionTrackingMiddleware2({
        filter(call) {
            calls.push(
                `${call.name} (${call.id}) <- (${call.parentCall && call.parentCall.id}) - filter`
            )
            return true
        },
        onStart(call) {
            calls.push(
                `${call.name} (${call.id}) <- (${call.parentCall && call.parentCall.id}) - onStart`
            )
        },
        onFinish(call, error) {
            calls.push(
                `${call.name} (${call.id}) <- (${
                    call.parentCall && call.parentCall.id
                }) - onFinish (error: ${!!error})`
            )
        }
    })

    const model = M.create({})

    addMiddleware(model, mware, false)

    expect(model.x).toBe(0)
    expect(model.y).toBe(0)
    expect(calls).toEqual([])

    const p = model.setX()
    expect(model.x).toBe(10)
    expect(model.y).toBe(0)
    expect(calls).toEqual(["setX (1) <- (undefined) - filter", "setX (1) <- (undefined) - onStart"])
    calls.length = 0

    await new Promise<void>(r =>
        setTimeout(() => {
            model.setY()
            r()
        }, 5)
    )
    expect(model.x).toBe(10)
    expect(model.y).toBe(10)
    expect(calls).toEqual([
        "setY (3) <- (undefined) - filter",
        "setY (3) <- (undefined) - onStart",
        "setY (3) <- (undefined) - onFinish (error: false)"
    ])
    calls.length = 0

    await p
    expect(model.x).toBe(10)
    expect(model.y).toBe(10)
    expect(calls).toEqual(["setX (1) <- (undefined) - onFinish (error: false)"])
    calls.length = 0
})

/**
 * Test that when createActionTrackingMiddleware2 is called with valid hooks and a synchronous action, it runs onStart and onFinish hooks.
 */
test("successful execution", () => {
    const M = types.model({}).actions(self => ({
        test() {}
    }))

    const calls: string[] = []

    const mware = createActionTrackingMiddleware2({
        filter(call) {
            calls.push(`${call.name} - filter`)
            return true
        },
        onStart(call) {
            calls.push(`${call.name} - onStart`)
        },
        onFinish(call, error) {
            calls.push(`${call.name} - onFinish (error: ${!!error})`)
        }
    })

    const model = M.create({})
    addMiddleware(model, mware, false)

    model.test()

    expect(calls).toEqual(["test - filter", "test - onStart", "test - onFinish (error: false)"])
})

/**
 * Test that when createActionTrackingMiddleware2 is called with valid hooks and an asynchronous action, it runs onStart and onFinish hooks.
 */
test("successful execution with async action", async () => {
    const M = types.model({}).actions(self => ({
        async test() {}
    }))

    const calls: string[] = []

    const mware = createActionTrackingMiddleware2({
        filter(call) {
            calls.push(`${call.name} - filter`)
            return true
        },
        onStart(call) {
            calls.push(`${call.name} - onStart`)
        },
        onFinish(call, error) {
            calls.push(`${call.name} - onFinish (error: ${!!error})`)
        }
    })

    const model = M.create({})
    addMiddleware(model, mware, false)

    await model.test()

    expect(calls).toEqual(["test - filter", "test - onStart", "test - onFinish (error: false)"])
})

/**
 * Test that when the filter returns true, the action is tracked. We check
 * this by checking that the onStart and onFinish hooks are called for `runThisOne`,
 * which is the name provided to the `filter` function.
 */
it("calls onStart and onFinish hooks for actions that pass the filter", () => {
    const M2 = types.model({}).actions(self => ({
        trackThisOne() {},
        doNotTrackThisOne() {}
    }))

    const calls: string[] = []

    const mware2 = createActionTrackingMiddleware2({
        filter(call) {
            return call.name === "trackThisOne"
        },
        onStart(call) {
            calls.push(`${call.name} - onStart`)
        },
        onFinish(call, error) {
            calls.push(`${call.name} - onFinish (error: ${!!error})`)
        }
    })

    const model2 = M2.create({})
    addMiddleware(model2, mware2, false)

    model2.trackThisOne()
    // We call this action to prove that it is not tracked since it fails - there's also a test for this below.
    model2.doNotTrackThisOne()

    expect(calls).toEqual(["trackThisOne - onStart", "trackThisOne - onFinish (error: false)"])
})
/**
 * Test that when the filter returns false, the action is not tracked. We check
 * this by checking that the onStart and onFinish hooks are not called for `doNotTrackThisOne`,
 */
it("does not call onStart and onFinish hooks for actions that do not pass the filter", () => {
    const M = types.model({}).actions(self => ({
        trackThisOne() {},
        doNotTrackThisOne() {}
    }))

    const calls: string[] = []

    const mware = createActionTrackingMiddleware2({
        filter(call) {
            return call.name === "trackThisOne"
        },
        onStart(call) {
            calls.push(`${call.name} - onStart`)
        },
        onFinish(call, error) {
            calls.push(`${call.name} - onFinish (error: ${!!error})`)
        }
    })

    const model = M.create({})
    addMiddleware(model, mware, false)

    model.doNotTrackThisOne()

    expect(calls).toEqual([])
})

/**
 * Test that parent actions and child actions have the expected order of operations -
 * if we had an action `a` that called an action `b1`, then `b2` inside `a`, the flow would be:
 *
 * - `filter(a)`
 * - `onStart(a)`
 *  - `filter(b1)`
 *  - `onStart(b1)`
 *  - `onFinish(b1)`
 *  - `filter(b2)`
 *  - `onStart(b2)`
 *  - `onFinish(b2)`
 * - `onFinish(a)`
 *
 * See https://mobx-state-tree.js.org/API/#createactiontrackingmiddleware2
 */
test("complete in the expected recursive order", () => {
    const M = types
        .model({})
        .actions(self => ({
            childAction1() {},
            childAction2() {}
        }))
        .actions(self => ({
            parentAction() {
                self.childAction1()
                self.childAction2()
            }
        }))

    const calls: string[] = []

    const mware = createActionTrackingMiddleware2({
        filter(call) {
            calls.push(`${call.name} - filter`)
            return true
        },
        onStart(call) {
            calls.push(`${call.name} - onStart`)
        },
        onFinish(call, error) {
            calls.push(`${call.name} - onFinish (error: ${!!error})`)
        }
    })

    const model = M.create({})
    addMiddleware(model, mware, false)

    model.parentAction()

    expect(calls).toEqual([
        "parentAction - filter",
        "parentAction - onStart",
        "childAction1 - filter",
        "childAction1 - onStart",
        "childAction1 - onFinish (error: false)",
        "childAction2 - filter",
        "childAction2 - onStart",
        "childAction2 - onFinish (error: false)",
        "parentAction - onFinish (error: false)"
    ])
})


================================================
FILE: __tests__/core/api.test.ts
================================================
import { expect, test } from "bun:test"
import { readFileSync } from "fs"
import * as mst from "../../src"

function stringToArray(s: string): string[] {
    return s.split(",").map(str => str.trim())
}

const METHODS_AND_INTERNAL_TYPES = stringToArray(`
    typecheck,
    escapeJsonPath,
    unescapeJsonPath,
    joinJsonPath,
    splitJsonPath,
    decorate,
    addMiddleware,
    isStateTreeNode,
    flow,
    castFlowReturn,
    applyAction,
    onAction,
    recordActions,
    createActionTrackingMiddleware,
    createActionTrackingMiddleware2,
    setLivelinessChecking,
    getLivelinessChecking,
    getType,
    getChildType,
    onPatch,
    onSnapshot,
    applyPatch,
    recordPatches,
    protect,
    unprotect,
    isProtected,
    applySnapshot,
    getSnapshot,
    hasParent,
    getParent,
    hasParentOfType,
    getParentOfType,
    getRoot,
    getPath,
    getPathParts,
    isRoot,
    resolvePath,
    resolveIdentifier,
    getIdentifier,
    tryResolve,
    getRelativePath,
    clone,
    detach,
    destroy,
    isAlive,
    addDisposer,
    getEnv,
    hasEnv,
    walk,
    getMembers,
    getPropertyMembers,
    cast,
    castToSnapshot,
    castToReferenceSnapshot,
    isType,
    isArrayType,
    isFrozenType,
    isIdentifierType,
    isLateType,
    isLiteralType,
    isMapType,
    isModelType,
    isOptionalType,
    isPrimitiveType,
    isReferenceType,
    isRefinementType,
    isUnionType,
    isValidReference,
    tryReference,
    types,
    t,
    getNodeId,
    getRunningActionContext,
    isActionContextChildOf,
    isActionContextThisOrChildOf,
    toGeneratorFunction,
    toGenerator
`)

const DEPRECATED_METHODS_AND_INTERNAL_TYPES = stringToArray(`
    setLivelynessChecking,
    process
`)

const METHODS = METHODS_AND_INTERNAL_TYPES.filter(s => s[0].toLowerCase() === s[0])

const INTERNAL_TYPES = METHODS_AND_INTERNAL_TYPES.filter(s => s[0].toUpperCase() === s[0])

const TYPES = stringToArray(`
    enumeration,
    model,
    compose,
    custom,
    reference,
    safeReference,
    union,
    optional,
    literal,
    maybe,
    maybeNull,
    refinement,
    string,
    boolean,
    number,
    integer,
    float,
    finite,
    bigint,
    Date,
    map,
    array,
    frozen,
    identifier,
    identifierNumber,
    late,
    lazy,
    undefined,
    null,
    snapshotProcessor
`)

test("correct api exposed", () => {
    expect(
        Object.keys(mst)
            .sort()
            .filter(key => (mst as any)[key] !== undefined) // filter out interfaces
            .filter(s => !DEPRECATED_METHODS_AND_INTERNAL_TYPES.includes(s))
    ).toEqual([...METHODS, ...INTERNAL_TYPES].sort())
})

test("correct types exposed", () => {
    expect(Object.keys(mst.types).sort()).toEqual(TYPES.sort())
})

test("types also exposed on t module", () => {
    expect(Object.keys(mst.t).sort()).toEqual(TYPES.sort())
})

test("all methods mentioned in API docs", () => {
    const apimd = readFileSync(__dirname + "/../../docs/API/index.md", "utf8")
    const missing = TYPES.map(type => "types." + type).filter(
        identifier => apimd.indexOf(identifier) === -1
    )
    missing.push(
        ...METHODS.filter(identifier => apimd.indexOf("#" + identifier.toLowerCase()) === -1)
    )
    expect(missing).toEqual(["types.lazy", "types"])
})

test("only accepted dependencies", () => {
    const validDeps: string[] = ["ts-essentials"]

    const deps =
        JSON.parse(readFileSync(__dirname + "/../../package.json", "utf8")).dependencies || {}

    const depNames = Object.keys(deps) || []
    expect(depNames.sort()).toEqual(validDeps.sort())
})


================================================
FILE: __tests__/core/array.test.ts
================================================
import {
    unprotect,
    onSnapshot,
    onPatch,
    clone,
    isAlive,
    applyPatch,
    getPath,
    applySnapshot,
    getSnapshot,
    types,
    IJsonPatch,
    setLivelinessChecking,
    detach,
    cast
} from "../../src"
import { observable, autorun, configure } from "mobx"
import { expect, test } from "bun:test"

const createTestFactories = () => {
    const ItemFactory = types.optional(
        types.model({
            to: "world"
        }),
        {}
    )
    const Factory = types.array(ItemFactory)
    return { Factory, ItemFactory }
}
// === FACTORY TESTS ===
test("it should create a factory", () => {
    const { Factory } = createTestFactories()
    expect(getSnapshot(Factory.create())).toEqual([])
})
test("it should succeed if not optional and no default provided", () => {
    const Factory = types.array(types.string)
    expect(getSnapshot(Factory.create())).toEqual([])
})
test("it should restore the state from the snapshot", () => {
    configure({
        useProxies: "never"
    })

    const { Factory } = createTestFactories()
    const instance = Factory.create([{ to: "universe" }])
    expect(getSnapshot(instance)).toEqual([{ to: "universe" }])
    expect("" + instance).toBe("AnonymousModel@/0") // just the normal to string
})
// === SNAPSHOT TESTS ===
test("it should emit snapshots", () => {
    const { Factory, ItemFactory } = createTestFactories()
    const doc = Factory.create()
    unprotect(doc)
    let snapshots: (typeof Factory.SnapshotType)[] = []
    onSnapshot(doc, snapshot => snapshots.push(snapshot))
    doc.push(ItemFactory.create())
    expect(snapshots).toEqual([[{ to: "world" }]])
})
test("it should apply snapshots", () => {
    const { Factory, ItemFactory } = createTestFactories()
    const doc = Factory.create()
    applySnapshot(doc, [{ to: "universe" }])
    expect(getSnapshot(doc)).toEqual([{ to: "universe" }])
})
test("it should return a snapshot", () => {
    const { Factory, ItemFactory } = createTestFactories()
    const doc = Factory.create()
    unprotect(doc)
    doc.push(ItemFactory.create())
    expect(getSnapshot(doc)).toEqual([{ to: "world" }])
})
// === PATCHES TESTS ===
test("it should emit add patches", () => {
    const { Factory, ItemFactory } = createTestFactories()
    const doc = Factory.create()
    unprotect(doc)
    let patches: IJsonPatch[] = []
    onPatch(doc, patch => patches.push(patch))
    doc.push(ItemFactory.create({ to: "universe" }))
    expect(patches).toEqual([{ op: "add", path: "/0", value: { to: "universe" } }])
})
test("it should apply an add patch", () => {
    const { Factory, ItemFactory } = createTestFactories()
    const doc = Factory.create()
    applyPatch(doc, { op: "add", path: "/0", value: { to: "universe" } })
    expect(getSnapshot(doc)).toEqual([{ to: "universe" }])
})
test("it should emit update patches", () => {
    const { Factory, ItemFactory } = createTestFactories()
    const doc = Factory.create()
    unprotect(doc)
    doc.push(ItemFactory.create())
    let patches: IJsonPatch[] = []
    onPatch(doc, patch => patches.push(patch))
    doc[0] = ItemFactory.create({ to: "universe" })
    expect(patches).toEqual([{ op: "replace", path: "/0", value: { to: "universe" } }])
})
test("it should apply an update patch", () => {
    const { Factory, ItemFactory } = createTestFactories()
    const doc = Factory.create()
    applyPatch(doc, { op: "replace", path: "/0", value: { to: "universe" } })
    expect(getSnapshot(doc)).toEqual([{ to: "universe" }])
})
test("it should emit remove patches", () => {
    const { Factory, ItemFactory } = createTestFactories()
    const doc = Factory.create()
    unprotect(doc)
    doc.push(ItemFactory.create())
    let patches: IJsonPatch[] = []
    onPatch(doc, patch => patches.push(patch))
    doc.splice(0)
    expect(patches).toEqual([{ op: "replace", path: "", value: [] }])
})
test("it should apply a remove patch", () => {
    const { Factory, ItemFactory } = createTestFactories()
    const doc = Factory.create()
    unprotect(doc)
    doc.push(ItemFactory.create())
    doc.push(ItemFactory.create({ to: "universe" }))
    applyPatch(doc, { op: "remove", path: "/0" })
    expect(getSnapshot(doc)).toEqual([{ to: "universe" }])
})
test("it should apply patches", () => {
    const { Factory, ItemFactory } = createTestFactories()
    const doc = Factory.create()
    applyPatch(doc, [
        { op: "add", path: "/0", value: { to: "mars" } },
        { op: "replace", path: "/0", value: { to: "universe" } }
    ])
    expect(getSnapshot(doc)).toEqual([{ to: "universe" }])
})
// === TYPE CHECKS ===
test("it should check the type correctly", () => {
    const { Factory } = createTestFactories()
    const doc = Factory.create()
    expect(Factory.is(doc)).toEqual(true)
    expect(Factory.is([])).toEqual(true)
    expect(Factory.is({})).toEqual(false)
    expect(Factory.is([{ to: "mars" }])).toEqual(true)
    expect(Factory.is([{ wrongKey: true }])).toEqual(true)
    expect(Factory.is([{ to: true }])).toEqual(false)
})
test("paths shoud remain correct when splicing", () => {
    const Task = types.model("Task", {
        done: false
    })
    const store = types
        .model({
            todos: types.array(Task)
        })
        .create({
            todos: [{}]
        })
    unprotect(store)
    expect(store.todos.map(getPath)).toEqual(["/todos/0"])
    store.todos.push({})
    expect(store.todos.map(getPath)).toEqual(["/todos/0", "/todos/1"])
    store.todos.unshift({})
    expect(store.todos.map(getPath)).toEqual(["/todos/0", "/todos/1", "/todos/2"])
    store.todos.splice(0, 2)
    expect(store.todos.map(getPath)).toEqual(["/todos/0"])
    store.todos.splice(0, 1, {}, {}, {})
    expect(store.todos.map(getPath)).toEqual(["/todos/0", "/todos/1", "/todos/2"])
    store.todos.remove(store.todos[1])
    expect(store.todos.map(getPath)).toEqual(["/todos/0", "/todos/1"])
})
test("items should be reconciled correctly when splicing - 1", () => {
    configure({
        useProxies: "never"
    })

    const Task = types.model("Task", {
        x: types.string
    })
    const a = Task.create({ x: "a" }),
        b = Task.create({ x: "b" }),
        c = Task.create({ x: "c" }),
        d = Task.create({ x: "d" })
    const store = types
        .model({
            todos: types.array(Task)
        })
        .create({
            todos: [a]
        })
    unprotect(store)
    expect(store.todos.slice()).toEqual([a])
    expect(isAlive(a)).toBe(true)
    store.todos.push(b)
    expect(store.todos.slice()).toEqual([a, b])
    store.todos.unshift(c)
    expect(store.todos.slice()).toEqual([c, a, b])
    store.todos.splice(0, 2)
    expect(store.todos.slice()).toEqual([b])
    expect(isAlive(a)).toBe(false)
    expect(isAlive(b)).toBe(true)
    expect(isAlive(c)).toBe(false)

    setLivelinessChecking("error")
    expect(() => store.todos.splice(0, 1, a, c, d)).toThrow(
        "You are trying to read or write to an object that is no longer part of a state tree. (Object type: 'Task', Path upon death: '/todos/1', Subpath: '', Action: ''). Either detach nodes first, or don't use objects after removing / replacing them in the tree."
    )
    store.todos.splice(0, 1, clone(a), clone(c), clone(d))
    expect(store.todos.map(_ => _.x)).toEqual(["a", "c", "d"])
})
test("items should be reconciled correctly when splicing - 2", () => {
    const Task = types.model("Task", {
        x: types.string
    })
    const a = Task.create({ x: "a" }),
        b = Task.create({ x: "b" }),
        c = Task.create({ x: "c" }),
        d = Task.create({ x: "d" })
    const store = types
        .model({
            todos: types.array(Task)
        })
        .create({
            todos: [a, b, c, d]
        })
    unprotect(store)
    store.todos.splice(2, 1, { x: "e" }, { x: "f" })
    // becomes, a, b, e, f, d
    expect(store.todos.length).toBe(5)
    expect(store.todos[0] === a).toBe(true)
    expect(store.todos[1] === b).toBe(true)
    expect(store.todos[2] !== c).toBe(true)
    expect(store.todos[2].x).toBe("e")
    expect(store.todos[3] !== d).toBe(true)
    expect(store.todos[3].x).toBe("f")
    expect(store.todos[4] === d).toBe(true) // preserved and moved
    expect(store.todos[4].x).toBe("d")
    expect(store.todos.map(getPath)).toEqual([
        "/todos/0",
        "/todos/1",
        "/todos/2",
        "/todos/3",
        "/todos/4"
    ])
    store.todos.splice(1, 3, { x: "g" })
    // becomes a, g, d
    expect(store.todos.length).toBe(3)
    expect(store.todos[0] === a).toBe(true)
    expect(store.todos[1].x).toBe("g")
    expect(store.todos[2].x).toBe("d")
    expect(store.todos[1] !== b).toBe(true)
    expect(store.todos[2] === d).toBe(true) // still original d
    expect(store.todos.map(getPath)).toEqual(["/todos/0", "/todos/1", "/todos/2"])
})
test("it should reconciliate keyed instances correctly", () => {
    const Store = types.model({
        todos: types.optional(
            types.array(
                types.model("Task", {
                    id: types.identifier,
                    task: "",
                    done: false
                })
            ),
            []
        )
    })
    const store = Store.create({
        todos: [
            { id: "1", task: "coffee", done: false },
            { id: "2", task: "tea", done: false },
            { id: "3", task: "biscuit", done: false }
        ]
    })
    expect(store.todos.map(todo => todo.task)).toEqual(["coffee", "tea", "biscuit"])
    expect(store.todos.map(todo => todo.done)).toEqual([false, false, false])
    expect(store.todos.map(todo => todo.id)).toEqual(["1", "2", "3"])
    const coffee = store.todos[0]
    const tea = store.todos[1]
    const biscuit = store.todos[2]
    applySnapshot(store, {
        todos: [
            { id: "2", task: "Tee", done: true },
            { id: "1", task: "coffee", done: true },
            { id: "4", task: "biscuit", done: false },
            { id: "5", task: "stuffz", done: false }
        ]
    })
    expect(store.todos.map(todo => todo.task)).toEqual(["Tee", "coffee", "biscuit", "stuffz"])
    expect(store.todos.map(todo => todo.done)).toEqual([true, true, false, false])
    expect(store.todos.map(todo => todo.id)).toEqual(["2", "1", "4", "5"])
    expect(store.todos[0] === tea).toBe(true)
    expect(store.todos[1] === coffee).toBe(true)
    expect(store.todos[2] === biscuit).toBe(false)
})
test("it correctly reconciliate when swapping", () => {
    const Task = types.model("Task", {})
    const Store = types.model({
        todos: types.optional(types.array(Task), [])
    })
    const s = Store.create()
    unprotect(s)
    const a = Task.create()
    const b = Task.create()
    s.todos.push(a, b)
    s.todos.replace([b, a])
    expect(s.todos[0] === b).toBe(true)
    expect(s.todos[1] === a).toBe(true)
    expect(s.todos.map(getPath)).toEqual(["/todos/0", "/todos/1"])
})
test("it correctly reconciliate when swapping using snapshots", () => {
    const Task = types.model("Task", {})
    const Store = types.model({
        todos: types.array(Task)
    })
    const s = Store.create()
    unprotect(s)
    const a = Task.create()
    const b = Task.create()
    s.todos.push(a, b)
    s.todos.replace([getSnapshot(b), getSnapshot(a)])
    expect(s.todos[0] === b).toBe(true)
    expect(s.todos[1] === a).toBe(true)
    expect(s.todos.map(getPath)).toEqual(["/todos/0", "/todos/1"])
    s.todos.push({})
    expect(s.todos[0] === b).toBe(true)
    expect(s.todos[1] === a).toBe(true)
    expect(s.todos.map(getPath)).toEqual(["/todos/0", "/todos/1", "/todos/2"])
})
test("it should not be allowed to add the same item twice to the same store", () => {
    const Task = types.model("Task", {})
    const Store = types.model({
        todos: types.optional(types.array(Task), [])
    })
    const s = Store.create()
    unprotect(s)
    const a = Task.create()
    s.todos.push(a)
    expect(() => {
        s.todos.push(a)
    }).toThrow(
        "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 '/todos/1', but it lives already at '/todos/0'"
    )
    const b = Task.create()
    expect(() => {
        s.todos.push(b, b)
    }).toThrow(
        "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 '/todos/2', but it lives already at '/todos/1'"
    )
})
test("it should support observable arrays", () => {
    const TestArray = types.array(types.number)
    const testArray = TestArray.create(observable([1, 2]))
    expect(testArray[0] === 1).toBe(true)
    expect(testArray.length === 2).toBe(true)
    expect(Array.isArray(testArray.slice())).toBe(true)
})

test("it should support observable arrays, array should be real when useProxies eq 'always'", () => {
    const TestArray = types.array(types.number)
    const testArray = TestArray.create(observable([1, 2]))
    expect(testArray[0] === 1).toBe(true)
    expect(testArray.length === 2).toBe(true)
    expect(Array.isArray(testArray)).toBe(true)
})

test("it should support observable arrays, array should be not real when useProxies eq 'never'", () => {
    configure({
        useProxies: "never"
    })

    const TestArray = types.array(types.number)
    const testArray = TestArray.create(observable([1, 2]))
    expect(testArray[0] === 1).toBe(true)
    expect(testArray.length === 2).toBe(true)
    expect(Array.isArray(testArray.slice())).toBe(true)
    expect(Array.isArray(testArray)).toBe(false)
})

test("it should correctly handle re-adding of the same objects", () => {
    const Store = types
        .model("Task", {
            objects: types.array(types.maybe(types.frozen()))
        })
        .actions(self => ({
            setObjects(objects: {}[]) {
                self.objects.replace(objects)
            }
        }))
    const store = Store.create({
        objects: []
    })
    expect(store.objects.slice()).toEqual([])
    const someObject = {}
    store.setObjects([someObject])
    expect(store.objects.slice()).toEqual([someObject])
    store.setObjects([someObject])
    expect(store.objects.slice()).toEqual([someObject])
})
test("it should work correctly for splicing primitive array", () => {
    const store = types.array(types.number).create([1, 2, 3])
    unprotect(store)
    store.splice(0, 1)
    expect(store.slice()).toEqual([2, 3])
    store.unshift(1)
    expect(store.slice()).toEqual([1, 2, 3])
    store.replace([4, 5])
    expect(store.slice()).toEqual([4, 5])
    store.clear()
    expect(store.slice()).toEqual([])
})
test("it should keep unchanged for structrual equalled snapshot", () => {
    const Store = types.model({
        todos: types.array(
            types.model("Task", {
                id: types.identifier,
                task: "",
                done: false
            })
        ),
        numbers: types.array(types.number)
    })
    const store = Store.create({
        todos: [
            { id: "1", task: "coffee", done: false },
            { id: "2", task: "tea", done: false },
            { id: "3", task: "biscuit", done: false }
        ],
        numbers: [1, 2, 3]
    })

    const values: boolean[][] = []
    autorun(() => {
        values.push(store.todos.map(todo => todo.done))
    })
    applySnapshot(store.todos, [
        { id: "1", task: "coffee", done: false },
        { id: "2", task: "tea", done: false },
        { id: "3", task: "biscuit", done: true }
    ])
    applySnapshot(store.todos, [
        { id: "1", task: "coffee", done: false },
        { id: "2", task: "tea", done: false },
        { id: "3", task: "biscuit", done: true }
    ])
    expect(values).toEqual([
        [false, false, false],
        [false, false, true]
    ])

    const values1: number[][] = []
    autorun(() => {
        values1.push(store.numbers.slice())
    })
    applySnapshot(store.numbers, [1, 2, 4])
    applySnapshot(store.numbers, [1, 2, 4])
    expect(values1).toEqual([
        [1, 2, 3],
        [1, 2, 4]
    ])
})

// === OPERATIONS TESTS ===
test("#1105 - it should return pop/shift'ed values for scalar arrays", () => {
    const ScalarArray = types
        .model({
            array: types.array(types.number)
        })
        .actions(self => {
            return {
                shift() {
                    return self.array.shift()
                }
            }
        })

    const test = ScalarArray.create({ array: [3, 5] })

    expect(test.shift()).toEqual(3)
    expect(test.shift()).toEqual(5)
})

test("it should return pop/shift'ed values for object arrays", () => {
    const TestObject = types.model({ id: types.string })
    const ObjectArray = types
        .model({
            array: types.array(TestObject)
        })
        .actions(self => {
            return {
                shift() {
                    return self.array.shift()
                },
                pop() {
                    return self.array.pop()
                }
            }
        })

    const test = ObjectArray.create({
        array: [{ id: "foo" }, { id: "mid" }, { id: "bar" }]
    })

    const foo = test.shift()!
    expect(isAlive(foo)).toBe(false)
    const bar = test.pop()!
    expect(isAlive(bar)).toBe(false)

    // we have to use clone or getSnapshot to access dead nodes data
    expect(clone(foo)).toEqual({ id: "foo" })
    expect(getSnapshot(bar)).toEqual({ id: "bar" })
})

test("#1173 - detaching an array should not eliminate its children", () => {
    const M = types.model({})
    const AM = types.array(M)
    const Store = types.model({ items: AM })
    const s = Store.create({ items: [{}, {}, {}] })
    const n0 = s.items[0]

    unprotect(s)

    const detachedItems = detach(s.items)
    expect(s.items).not.toBe(detachedItems)
    expect(s.items.length).toBe(0)
    expect(detachedItems.length).toBe(3)
    expect(detachedItems[0]).toBe(n0)
})

test("initializing an array instance from another array instance should end up in the same instance", () => {
    const A = types.array(types.number)
    const a1 = A.create([1, 2, 3])
    const a2 = A.create(a1)
    expect(a1).toBe(a2)
    expect(getSnapshot(a1)).toEqual([1, 2, 3])
})

test("assigning filtered instances works", () => {
    const Task = types.model("Task", {
        done: false
    })
    const store = types
        .model({
            todos: types.array(Task)
        })
        .actions(self => ({
            clearFinishedTodos() {
                self.todos = cast(self.todos.filter(todo => !todo.done))
            }
        }))
        .create({
            todos: [{ done: true }, { done: false }, { done: true }]
        })

    expect(store.todos.length).toBe(3)
    const done = store.todos.filter(t => t.done)
    const notDone = store.todos.filter(t => !t.done)
    expect(store.todos.every(t => isAlive(t)))
    store.clearFinishedTodos()
    expect(store.todos.length).toBe(1)
    expect(store.todos[0]).toBe(notDone[0])
    expect(done.every(t => !isAlive(t))).toBe(true)
    expect(notDone.every(t => isAlive(t))).toBe(true)
})

test("#1676 - should accept read-only arrays", () => {
    const ArrayType = types.array(types.string)
    const data = ["foo", "bar"] as const
    const instance = ArrayType.create(data)
    expect(getSnapshot(instance)).toEqual(["foo", "bar"])
})


================================================
FILE: __tests__/core/async.test.ts
================================================
import { configure, reaction } from "mobx"
import {
    addMiddleware,
    decorate,
    destroy,
    flow,
    IMiddlewareEvent,
    IMiddlewareEventType,
    IMiddlewareHandler,
    recordActions,
    toGenerator,
    // TODO: export IRawActionCall
    toGeneratorFunction,
    types
} from "../../src"
import { expect, test } from "bun:test"
import type { Writable } from "ts-essentials"

function delay<TV>(time: number, value: TV, shouldThrow = false): Promise<TV> {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            if (shouldThrow) reject(value)
            else resolve(value)
        }, time)
    })
}

async function testCoffeeTodo(
    generator: (
        self: any
    ) => (str: string) => Generator<Promise<any>, string | void | undefined, undefined>,
    shouldError: boolean,
    resultValue: string | undefined,
    producedCoffees: any[]
) {
    const Todo = types
        .model({
            title: "get coffee"
        })
        .actions(self => ({
            startFetch: flow(generator(self))
        }))

    const events: IMiddlewareEvent[] = []
    const t1 = Todo.create({})
    addMiddleware(t1, (c, next) => {
        events.push(c)
        return next(c)
    })

    const coffees: any[] = []
    reaction(
        () => t1.title,
        coffee => coffees.push(coffee)
    )

    try {
        configure({ enforceActions: "observed" })
        const result = await t1.startFetch("black")
        expect(shouldError).toBe(false)
        expect(result).toBe(resultValue)
    } catch (error) {
        expect(shouldError).toBe(true)
    } finally {
        configure({ enforceActions: "never" })
    }

    expect(coffees).toEqual(producedCoffees)
    const filtered = filterRelevantStuff(events)
    expect(filtered).toMatchSnapshot()
}
test("flow happens in single ticks", async () => {
    const X = types
        .model({
            y: 1
        })
        .actions(self => ({
            p: flow(function* () {
                self.y++
                self.y++
                yield delay(1, true, false)
                self.y++
                self.y++
            })
        }))
    const x = X.create()
    const values: number[] = []
    reaction(
        () => x.y,
        v => values.push(v)
    )

    await x.p()
    expect(x.y).toBe(5)
    expect(values).toEqual([3, 5])
})
test("can handle async actions", () => {
    testCoffeeTodo(
        self =>
            function* fetchData(kind: string) {
                self.title = "getting coffee " + kind
                self.title = yield delay(100, "drinking coffee")
                return "awake"
            },
        false,
        "awake",
        ["getting coffee black", "drinking coffee"]
    )
})
test("can handle erroring actions", () => {
    testCoffeeTodo(
        self =>
            function* fetchData(kind: string) {
                throw kind
            },
        true,
        "black",
        []
    )
})
test("can handle try catch", () => {
    testCoffeeTodo(
        self =>
            function* fetchData(kind: string) {
                try {
                    yield delay(10, "tea", true)
                    return undefined
                } catch (e) {
                    self.title = e
                    return "biscuit"
                }
            },
        false,
        "biscuit",
        ["tea"]
    )
})
test("empty sequence works", () => {
    testCoffeeTodo(() => function* fetchData(kind: string) {}, false, undefined, [])
})
test("can handle throw from yielded promise works", () => {
    testCoffeeTodo(
        () =>
            function* fetchData(kind: string) {
                yield delay(10, "x", true)
            },
        true,
        "x",
        []
    )
})
test("typings", async () => {
    const M = types.model({ title: types.string }).actions(self => {
        function* a(x: string) {
            yield delay(10, "x", false)
            self.title = "7"
            return 23
        }
        // tslint:disable-next-line:no-shadowed-variable
        const b = flow(function* b(x: string) {
            yield delay(10, "x", false)
            self.title = "7"
            return 24
        })
        return { a: flow(a), b }
    })
    const m1 = M.create({ title: "test " })
    const resA = m1.a("z")
    const resB = m1.b("z")
    const [x1, x2] = await Promise.all([resA, resB])
    expect(x1).toBe(23)
    expect(x2).toBe(24)
})
test("typings", async () => {
    const M = types.model({ title: types.string }).actions(self => {
        function* a(x: string) {
            yield delay(10, "x", false)
            self.title = "7"
            return 23
        }
        // tslint:disable-next-line:no-shadowed-variable
        const b = flow(function* b(x: string) {
            yield delay(10, "x", false)
            self.title = "7"
            return 24
        })
        return { a: flow(a), b }
    })
    const m1 = M.create({ title: "test " })
    const resA = m1.a("z")
    const resB = m1.b("z")
    const [x1, x2] = await Promise.all([resA, resB])
    expect(x1).toBe(23)
    expect(x2).toBe(24)
})
test("recordActions should only emit invocation", async () => {
    let calls = 0
    const M = types
        .model({
            title: types.string
        })
        .actions(self => {
            function* a(x: string) {
                yield delay(10, "x", false)
                calls++
                return 23
            }
            return {
                a: flow(a)
            }
        })
    const m1 = M.create({ title: "test " })
    const recorder = recordActions(m1)
    await m1.a("x")

    recorder.stop()
    expect(recorder.actions).toEqual([
        {
            args: ["x"],
            name: "a",
            path: ""
        }
    ])
    expect(calls).toBe(1)
    recorder.replay(m1)

    await new Promise(resolve => setTimeout(resolve, 50))
    expect(calls).toBe(2)
})
test("can handle nested async actions", () => {
    // tslint:disable-next-line:no-shadowed-variable
    const uppercase = flow(function* uppercase(value: string) {
        const res = yield delay(20, value.toUpperCase())
        return res
    })
    testCoffeeTodo(
        self =>
            function* fetchData(kind: string) {
                self.title = yield uppercase("drinking " + kind)
                return self.title
            },
        false,
        "DRINKING BLACK",
        ["DRINKING BLACK"]
    )
})
test("can handle nested async actions when using decorate", async () => {
    const events: [IMiddlewareEventType, string][] = []
    const middleware: IMiddlewareHandler = (call, next) => {
        events.push([call.type, call.name])
        return next(call)
    }
    // tslint:disable-next-line:no-shadowed-variable
    const uppercase = flow(function* uppercase(value: string) {
        const res = yield delay(20, value.toUpperCase())
        return res
    })
    const Todo = types.model({}).actions(self => {
        // tslint:disable-next-line:no-shadowed-variable
        const act = flow(function* act(value: string) {
            return yield uppercase(value)
        })
        return { act: decorate(middleware, act) }
    })

    const res = await Todo.create().act("x")
    expect(res).toBe("X")
    expect(events).toEqual([
        ["action", "act"],
        ["flow_spawn", "act"],
        ["flow_resume", "act"],
        ["flow_resume", "act"],
        ["flow_return", "act"]
    ])
})

test("flow gain back control when node become not alive during yield", async () => {
    expect.assertions(2)
    const rejectError = new Error("Reject Error")
    const MyModel = types.model({}).actions(() => {
        return {
            doAction() {
                return flow(function* () {
                    try {
                        yield delay(20, "").then(() => Promise.reject(rejectError))
                    } catch (e) {
                        expect(e).toEqual(rejectError)
                        throw e
                    }
                })()
            }
        }
    })

    const m = MyModel.create({})
    const p = m.doAction()
    destroy(m)
    try {
        await p
    } catch (e) {
        expect(e).toEqual(rejectError)
    }
})

function filterRelevantStuff(stuff: Partial<Writable<IMiddlewareEvent>>[]) {
    return stuff.map(x => {
        delete x.context
        delete x.tree
        return x
    })
}

test("flow typings", async () => {
    const promise = Promise.resolve()

    const M = types.model({ x: 5 }).actions(self => ({
        // should be () => Promise<void>
        voidToVoid: flow(function* () {
            yield promise
        }), // should be (val: number) => Promise<number>
        numberToNumber: flow(function* (val: number) {
            yield promise
            return val
        }), // should be () => Promise<number>
        voidToNumber: flow(function* () {
            yield promise
            return Promise.resolve(2)
        })
    }))

    const m = M.create()

    // these should compile
    const a: void = await m.voidToVoid()
    expect(a).toBe(undefined)
    const b: number = await m.numberToNumber(4)
    expect(b).toBe(4)
    const c: number = await m.voidToNumber()
    expect(c).toBe(2)
    await m.voidToNumber().then(d => {
        const _d: number = d
        expect(_d).toBe(2)
    })
})

/**
 * Detect explicit `any` type.
 * https://stackoverflow.com/a/55541672/4289902
 */
type IfAny<T, Y, N> = 0 extends 1 & T ? Y : N

/**
 * Ensure that the type of the passed value is of the expected type, and is NOT the TypeScript `any` type
 */
function ensureNotAnyType<TExpected, TActual>(value: IfAny<TActual, never, TExpected>) {}

test("yield* typings for toGeneratorFunction", async () => {
    const voidPromise = () => Promise.resolve()
    const numberPromise = () => Promise.resolve(7)
    const stringWithArgsPromise = (input1: string, input2: boolean) =>
        Promise.resolve("test-result")

    const voidGen = toGeneratorFunction(voidPromise)
    const numberGen = toGeneratorFunction(numberPromise)
    const stringWithArgsGen = toGeneratorFunction(stringWithArgsPromise)

    const M = types.model({ x: 5 }).actions(self => {
        function* testAction() {
            const voidResult = yield* voidGen()
            ensureNotAnyType<void, typeof voidResult>(voidResult)

            const numberResult = yield* numberGen()
            ensureNotAnyType<number, typeof numberResult>(numberResult)

            const stringResult = yield* stringWithArgsGen("input", true)
            ensureNotAnyType<string, typeof stringResult>(stringResult)

            return stringResult
        }

        return {
            testAction: flow(testAction)
        }
    })

    const m = M.create()

    const result = await m.testAction()
    ensureNotAnyType<string, typeof result>(result)
    expect(result).toBe("test-result")
})

test("yield* typings for toGenerator", async () => {
    const voidPromise = () => Promise.resolve()
    const numberPromise = () => Promise.resolve(7)
    const stringWithArgsPromise = (input1: string, input2: boolean) =>
        Promise.resolve("test-result")

    const M = types.model({ x: 5 }).actions(self => {
        function* testAction() {
            const voidResult = yield* toGenerator(voidPromise())
            ensureNotAnyType<void, typeof voidResult>(voidResult)

            const numberResult = yield* toGenerator(numberPromise())
            ensureNotAnyType<number, typeof numberResult>(numberResult)

            const stringResult = yield* toGenerator(stringWithArgsPromise("input", true))
            ensureNotAnyType<string, typeof stringResult>(stringResult)

            return stringResult
        }

        return {
            testAction: flow(testAction)
        }
    })

    const m = M.create()

    const result = await m.testAction()
    ensureNotAnyType<string, typeof result>(result)
    expect(result).toBe("test-result")
})


================================================
FILE: __tests__/core/bigint.test.ts
================================================
import { t } from "../../src"
import { Hook, NodeLifeCycle } from "../../src/internal"
import { describe, it, expect, test } from "bun:test"

describe("types.bigint", () => {
    describe("methods", () => {
        describe("create", () => {
            describe("with no arguments", () => {
                if (process.env.NODE_ENV !== "production") {
                    it("should throw an error in development", () => {
                        expect(() => {
                            t.bigint.create()
                        }).toThrow()
                    })
                }
            })
            describe("with a bigint argument", () => {
                it("should return a bigint", () => {
                    const n = t.bigint.create(BigInt(1))
                    expect(typeof n).toBe("bigint")
                })
            })
            describe("with a number argument", () => {
                it("should return a bigint", () => {
                    const n = t.bigint.create(1)
                    expect(typeof n).toBe("bigint")
                    expect(n).toBe(BigInt(1))
                })
            })
            describe("with a string argument", () => {
                it("should return a bigint", () => {
                    const n = t.bigint.create("2")
                    expect(typeof n).toBe("bigint")
                    expect(n).toBe(BigInt(2))
                })
            })
            describe("with argument of different types", () => {
                const testCases = [
                    null,
                    undefined,
                    true,
                    [],
                    function () {},
                    new Date(),
                    /a/,
                    new Map(),
                    new Set(),
                    Symbol(),
                    new Error()
                ]

                if (process.env.NODE_ENV !== "production") {
                    testCases.forEach(testCase => {
                        it(`should throw an error when passed ${JSON.stringify(testCase)}`, () => {
                            expect(() => {
                                t.bigint.create(testCase as any)
                            }).toThrow()
                        })
                    })
                }
            })
        })
        describe("describe", () => {
            it("should return the value 'bigint'", () => {
                const description = t.bigint.describe()
                expect(description).toBe("bigint")
            })
        })
        describe("getSnapshot", () => {
            it("should return the value as string (JSON-safe)", () => {
                const n = t.bigint.instantiate(null, "", {}, BigInt(1))
                const snapshot = t.bigint.getSnapshot(n)
                expect(snapshot).toBe("1")
                expect(typeof snapshot).toBe("string")
            })
        })
        describe("getSubtype", () => {
            it("should return null", () => {
                const subtype = t.bigint.getSubTypes()
                expect(subtype).toBe(null)
            })
        })
        describe("instantiate", () => {
            if (process.env.NODE_ENV !== "production") {
                describe("with invalid arguments", () => {
                    it("should throw when passed undefined", () => {
                        expect(() => {
                            t.bigint.instantiate(null, "", {}, undefined as any)
                        }).toThrow()
                    })
                })
            }
            describe("with a bigint argument", () => {
                it("should return an object", () => {
                    const n = t.bigint.instantiate(null, "", {}, BigInt(1))
                    expect(typeof n).toBe("object")
                })
            })
        })
        describe("is", () => {
            describe("with a bigint argument", () => {
                it("should return true", () => {
                    const result = t.bigint.is(BigInt(1))
                    expect(result).toBe(true)
                })
            })
            describe("with argument of different types", () => {
                const testCases = [
                    null,
                    undefined,
                    true,
                    [],
                    function () {},
                    new Date(),
                    /a/,
                    new Map(),
                    new Set(),
                    Symbol(),
                    new Error()
                ]

                testCases.forEach(testCase => {
                    it(`should return false when passed ${JSON.stringify(testCase)}`, () => {
                        const result = t.bigint.is(testCase as any)
                        expect(result).toBe(false)
                    })
                })
            })
            describe("with a string argument", () => {
                it("should return true (string is valid snapshot input)", () => {
                    expect(t.bigint.is("1")).toBe(true)
                })
            })
            describe("with a number argument", () => {
                it("should return true (number is valid snapshot input)", () => {
                    expect(t.bigint.is(1)).toBe(true)
                })
            })
        })
        describe("isAssignableFrom", () => {
            describe("with a bigint argument", () => {
                it("should return true", () => {
                    const result = t.bigint.isAssignableFrom(t.bigint)
                    expect(result).toBe(true)
                })
            })
            describe("with argument of different types", () => {
                const testCases = [
                    t.Date,
                    t.boolean,
                    t.finite,
                    t.float,
                    t.identifier,
                    t.identifierNumber,
                    t.integer,
                    t.null,
                    t.string,
                    t.undefined
                ]

                testCases.forEach(testCase => {
                    it(`should return false when passed ${JSON.stringify(testCase)}`, () => {
                        const result = t.bigint.isAssignableFrom(testCase as any)
                        expect(result).toBe(false)
                    })
                })
            })
        })
        describe("validate", () => {
            describe("with a bigint, string or number argument", () => {
                it("should return with no validation errors for bigint", () => {
                    const result = t.bigint.validate(BigInt(1), [])
                    expect(result).toEqual([])
                })
                it("should return with no validation errors for string", () => {
                    const result = t.bigint.validate("1", [])
                    expect(result).toEqual([])
                })
                it("should return with no validation errors for number", () => {
                    const result = t.bigint.validate(1, [])
                    expect(result).toEqual([])
                })
            })
            describe("with argument of different types", () => {
                const testCases = [
                    null,
                    undefined,
                    true,
                    [],
                    function () {},
                    new Date(),
                    /a/,
                    new Map(),
                    new Set(),
                    Symbol(),
                    new Error()
                ]

                testCases.forEach(testCase => {
                    it(`should return with a validation error when passed ${JSON.stringify(
                        testCase
                    )}`, () => {
                        const result = t.bigint.validate(testCase as any, [])
                        expect(result).toEqual([
                            {
                                context: [],
                                message: "Value is not a bigint",
                                value: testCase
                            }
                        ])
                    })
                })
            })
        })
    })
    describe("properties", () => {
        describe("flags", () => {
            test("return the correct value", () => {
                const flags = t.bigint.flags
                expect(flags).toBe(1 << 23)
            })
        })
        describe("identifierAttribute", () => {
            test("returns undefined", () => {
                const identifierAttribute = t.bigint.identifierAttribute
                expect(identifierAttribute).toBeUndefined()
            })
        })
        describe("isType", () => {
            test("returns true", () => {
                const isType = t.bigint.isType
                expect(isType).toBe(true)
            })
        })
        describe("name", () => {
            test('returns "bigint"', () => {
                const name = t.bigint.name
                expect(name).toBe("bigint")
            })
        })
    })
    describe("instance", () => {
        describe("methods", () => {
            describe("aboutToDie", () => {
                it("calls the beforeDetach hook", () => {
                    const n = t.bigint.instantiate(null, "", {}, BigInt(1))
                    let called = false
                    n.registerHook(Hook.beforeDestroy, () => {
                        called = true
                    })
                    n.aboutToDie()
                    expect(called).toBe(true)
                })
            })
            describe("die", () => {
                it("kills the node", () => {
                    const n = t.bigint.instantiate(null, "", {}, BigInt(1))
                    n.die()
                    expect(n.isAlive).toBe(false)
                })
                it("should mark the node as dead", () => {
                    const n = t.bigint.instantiate(null, "", {}, BigInt(1))
                    n.die()
                    expect(n.state).toBe(NodeLifeCycle.DEAD)
                })
            })
            describe("finalizeCreation", () => {
                it("should mark the node as finalized", () => {
                    const n = t.bigint.instantiate(null, "", {}, BigInt(1))
                    n.finalizeCreation()
                    expect(n.state).toBe(NodeLifeCycle.FINALIZED)
                })
            })
            describe("finalizeDeath", () => {
                it("should mark the node as dead", () => {
                    const n = t.bigint.instantiate(null, "", {}, BigInt(1))
                    n.finalizeDeath()
                    expect(n.state).toBe(NodeLifeCycle.DEAD)
                })
            })
            describe("getReconciliationType", () => {
                it("should return the correct type", () => {
                    const n = t.bigint.instantiate(null, "", {}, BigInt(1))
                    const type = n.getReconciliationType()
                    expect(type).toBe(t.bigint)
                })
            })
            describe("getSnapshot", () => {
                it("should return the value as string (JSON-safe)", () => {
                    const n = t.bigint.instantiate(null, "", {}, BigInt(1))
                    const snapshot = n.getSnapshot()
                    expect(snapshot).toBe("1")
                    expect(typeof snapshot).toBe("string")
                })
            })
            describe("registerHook", () => {
                it("should register a hook and call it", () => {
                    const n = t.bigint.instantiate(null, "", {}, BigInt(1))
                    let called = false
                    n.registerHook(Hook.beforeDestroy, () => {
                        called = true
                    })

                    n.die()

                    expect(called).toBe(true)
                })
            })
            describe("setParent", () => {
                if (process.env.NODE_ENV !== "production") {
                    describe("with null", () => {
                        it("should throw an error", () => {
                            const n = t.bigint.instantiate(null, "", {}, BigInt(1))
                            expect(() => {
                                n.setParent(null, "foo")
                            }).toThrow()
                        })
                    })
                    describe("with a parent object", () => {
                        it("should throw an error", () => {
                            const Parent = t.model({
                                child: t.bigint
                            })

                            const parent = Parent.create({ child: BigInt(1) })

                            const n = t.bigint.instantiate(null, "", {}, BigInt(1))

                            expect(() => {
                                // @ts-ignore
                                n.setParent(parent, "bar")
                            }).toThrow(
                                "[mobx-state-tree] assertion failed: scalar nodes cannot change their parent"
                            )
                        })
                    })
                }
            })
        })
    })
})


================================================
FILE: __tests__/core/boolean.test.ts
================================================
import { t } from "../../src"
import { Hook, NodeLifeCycle } from "../../src/internal"
import { describe, expect, it, test } from "bun:test"

describe("types.boolean", () => {
    describe("methods", () => {
        describe("create", () => {
            describe("with no arguments", () => {
                if (process.env.NODE_ENV !== "production") {
                    it("should throw an error in development", () => {
                        expect(() => {
                            t.boolean.create()
                        }).toThrow()
                    })
                }
            })
            describe("with a boolean argument", () => {
                it("should return a boolean", () => {
                    const n = t.boolean.create(true)
                    expect(typeof n).toBe("boolean")
                })
            })
            describe("with argument of different types", () => {
                const testCases = [
                    null,
                    undefined,
                    "string",
                    1,
                    [],
                    function () {},
                    new Date(),
                    /a/,
                    new Map(),
                    new Set(),
                    Symbol(),
                    new Error(),
                    Infinity,
                    NaN
                ]

                if (process.env.NODE_ENV !== "production") {
                    testCases.forEach(testCase => {
                        it(`should throw an error when passed ${JSON.stringify(testCase)}`, () => {
                            expect(() => {
                                t.boolean.create(testCase as any)
                            }).toThrow()
                        })
                    })
                }
            })
        })
        describe("describe", () => {
            it("should return the value 'boolean'", () => {
                const description = t.boolean.describe()
                expect(description).toBe("boolean")
            })
        })
        describe("getSnapshot", () => {
            it("should return the value passed in", () => {
                const b = t.boolean.instantiate(null, "", {}, true)
                const snapshot = t.boolean.getSnapshot(b)
                expect(snapshot).toBe(true)
            })
        })
        describe("getSubtype", () => {
            it("should return null", () => {
                const subtype = t.boolean.getSubTypes()
                expect(subtype).toBe(null)
            })
        })
        describe("instantiate", () => {
            if (process.env.NODE_ENV !== "production") {
                describe("with invalid arguments", () => {
                    it("should not throw an error", () => {
                        expect(() => {
                            // @ts-ignore
                            t.boolean.instantiate()
                        }).not.toThrow()
                    })
                })
            }
            describe("with a boolean argument", () => {
                it("should return an object", () => {
                    const b = t.boolean.instantiate(null, "", {}, true)
                    expect(typeof b).toBe("object")
                })
            })
        })
        describe("is", () => {
            describe("with a boolean argument", () => {
                it("should return true", () => {
                    const result = t.boolean.is(true)
                    expect(result).toBe(true)
                })
            })
            describe("with argument of different types", () => {
                const testCases = [
                    null,
                    undefined,
                    "string",
                    1,
                    [],
                    function () {},
                    new Date(),
                    /a/,
                    new Map(),
                    new Set(),
                    Symbol(),
                    new Error(),
                    Infinity,
                    NaN
                ]

                testCases.forEach(testCase => {
                    it(`should return false when passed ${JSON.stringify(testCase)}`, () => {
                        const result = t.boolean.is(testCase as any)
                        expect(result).toBe(false)
                    })
                })
            })
        })
        describe("isAssignableFrom", () => {
            describe("with a boolean argument", () => {
                it("should return true", () => {
                    const result = t.boolean.isAssignableFrom(t.boolean)
                    expect(result).toBe(true)
                })
            })
            describe("with argument of different types", () => {
                const testCases = [
                    t.Date,
                    t.number,
                    t.finite,
                    t.float,
                    t.identifier,
                    t.identifierNumber,
                    t.integer,
                    t.null,
                    t.string,
                    t.undefined
                ]

                testCases.forEach(testCase => {
                    it(`should return false when passed ${JSON.stringify(testCase)}`, () => {
                        const result = t.boolean.isAssignableFrom(testCase as any)
                        expect(result).toBe(false)
                    })
                })
            })
        })
        // TODO: we need to test this, but to be honest I'm not sure what the expected behavior is on single boolean nodes.
        describe.skip("reconcile", () => {})
        describe("validate", () => {
            describe("with a boolean argument", () => {
                it("should return with no validation errors", () => {
                    const result = t.boolean.validate(true, [])
                    expect(result).toEqual([])
                })
            })
            describe("with argument of different types", () => {
                const testCases = [
                    null,
                    undefined,
                    "string",
                    1,
                    [],
                    function () {},
                    new Date(),
                    /a/,
                    new Map(),
                    new Set(),
                    Symbol(),
                    new Error(),
                    Infinity,
                    NaN
                ]

                testCases.forEach(testCase => {
                    it(`should return with a validation error when passed ${JSON.stringify(
                        testCase
                    )}`, () => {
                        const result = t.boolean.validate(testCase as any, [])
                        expect(result).toEqual([
                            {
                                context: [],
                                message: "Value is not a boolean",
                                value: testCase
                            }
                        ])
                    })
                })
            })
        })
    })
    describe("properties", () => {
        describe("flags", () => {
            test("return the correct value", () => {
                const flags = t.boolean.flags
                expect(flags).toBe(4)
            })
        })
        describe("identifierAttribute", () => {
            // We don't have a way to set the identifierAttribute on a primitive type, so this should return undefined.
            test("returns undefined", () => {
                const identifierAttribute = t.boolean.identifierAttribute
                expect(identifierAttribute).toBeUndefined()
            })
        })
        describe("isType", () => {
            test("returns true", () => {
                const isType = t.boolean.isType
                expect(isType).toBe(true)
            })
        })
        describe("name", () => {
            test('returns "boolean"', () => {
                const name = t.boolean.name
                expect(name).toBe("boolean")
            })
        })
    })
    describe("instance", () => {
        describe("methods", () => {
            describe("aboutToDie", () => {
                it("calls the beforeDetach hook", () => {
                    const b = t.boolean.instantiate(null, "", {}, true)
                    let called = false
                    b.registerHook(Hook.beforeDestroy, () => {
                        called = true
                    })
                    b.aboutToDie()
                    expect(called).toBe(true)
                })
            })
            describe("die", () => {
                it("kills the node", () => {
                    const b = t.boolean.instantiate(null, "", {}, true)
                    b.die()
                    expect(b.isAlive).toBe(false)
                })
                it("should mark the node as dead", () => {
                    const b = t.boolean.instantiate(null, "", {}, true)
                    b.die()
                    expect(b.state).toBe(NodeLifeCycle.DEAD)
                })
            })
            describe("finalizeCreation", () => {
                it("should mark the node as finalized", () => {
                    const b = t.boolean.instantiate(null, "", {}, true)
                    b.finalizeCreation()
                    expect(b.state).toBe(NodeLifeCycle.FINALIZED)
                })
            })
            describe("finalizeDeath", () => {
                it("should mark the node as dead", () => {
                    const b = t.boolean.instantiate(null, "", {}, true)
                    b.finalizeDeath()
                    expect(b.state).toBe(NodeLifeCycle.DEAD)
                })
            })
            describe("getReconciliationType", () => {
                it("should return the correct type", () => {
                    const b = t.boolean.instantiate(null, "", {}, true)
                    const type = b.getReconciliationType()
                    expect(type).toBe(t.boolean)
                })
            })
            describe("getSnapshot", () => {
                it("should return the value passed in", () => {
                    const b = t.boolean.instantiate(null, "", {}, true)
                    const snapshot = b.getSnapshot()
                    expect(snapshot).toBe(true)
                })
            })
            describe("registerHook", () => {
                it("should register a hook and call it", () => {
                    const b = t.boolean.instantiate(null, "", {}, true)
                    let called = false
                    b.registerHook(Hook.beforeDestroy, () => {
                        called = true
                    })

                    b.die()

                    expect(called).toBe(true)
                })
            })
            describe("setParent", () => {
                if (process.env.NODE_ENV !== "production") {
                    describe("with null", () => {
                        it("should throw an error", () => {
                            const b = t.boolean.instantiate(null, "", {}, true)
                            expect(() => {
                                b.setParent(null, "foo")
                            }).toThrow()
                        })
                    })
                    describe("with a parent object", () => {
                        it("should throw an error", () => {
                            const Parent = t.model({
                                child: t.boolean
                            })

                            const parent = Parent.create({ child: true })

                            const b = t.boolean.instantiate(null, "", {}, true)

                            expect(() => {
                                // @ts-ignore
                                b.setParent(parent, "bar")
                            }).toThrow(
                                "[mobx-state-tree] assertion failed: scalar nodes cannot change their parent"
                            )
                        })
                    })
                }
            })
        })
    })
})


================================================
FILE: __tests__/core/boxes-store.test.ts
================================================
import { values } from "mobx"
import {
    types,
    getParent,
    hasParent,
    recordPatches,
    unprotect,
    getSnapshot,
    Instance
} from "../../src"
import { expect, test } from "bun:test"

export const Box = types
    .model("Box", {
        id: types.identifier,
        name: "",
        x: 0,
        y: 0
    })
    .views(self => ({
        get width() {
            return self.name.length * 15
        },
        get isSelected(): boolean {
            if (!hasParent(self)) return false
            return getParent<typeof Store>(getParent(self)).selection === self
        }
    }))
    .actions(self => {
        function move(dx: number, dy: number) {
            self.x += dx
            self.y += dy
        }
        function setName(newName: string) {
            self.name = newName
        }
        return {
            move,
            setName
        }
    })
export const Arrow = types.model("Arrow", {
    id: types.identifier,
    from: types.reference(Box),
    to: types.reference(Box)
})
export const Store = types
    .model("Store", {
        boxes: types.map(Box),
        arrows: types.array(Arrow),
        selection: types.reference(Box)
    })
    .actions(self => {
        function afterCreate() {
            unprotect(self)
        }
        function addBox(id: string, name: string, x: number, y: number) {
            const box = Box.create({ name, x, y, id })
            self.boxes.put(box)
            return box
        }
        function addArrow(id: string, from: string, to: string) {
            self.arrows.push(Arrow.create({ id, from, to }))
        }
        function setSelection(selection: Instance<typeof Box>) {
            self.selection = selection
        }
        function createBox(
            id: string,
            name: string,
            x: number,
            y: number,
            source: Instance<typeof Box> | null | undefined,
            arrowId: string | null
        ) {
            const box = addBox(id, name, x, y)
            setSelection(box)
            if (source) addArrow(arrowId!, source.id, box.id)
        }
        return {
            afterCreate,
            addBox,
            addArrow,
            setSelection,
            createBox
        }
    })
function createStore() {
    return Store.create({
        boxes: {
            cc: { id: "cc", name: "Rotterdam", x: 100, y: 100 },
            aa: { id: "aa", name: "Bratislava", x: 650, y: 300 }
        },
        arrows: [{ id: "dd", from: "cc", to: "aa" }],
        selection: "aa"
    })
}
test("store is deserialized correctly", () => {
    const s = createStore()
    expect(s.boxes.size).toBe(2)
    expect(s.arrows.length).toBe(1)
    expect(s.selection === s.boxes.get("aa")).toBe(true)
    expect(s.arrows[0].from.name).toBe("Rotterdam")
    expect(s.arrows[0].to.name).toBe("Bratislava")
    expect(values(s.boxes).map(b => b.isSelected)).toEqual([false, true])
})
test("store emits correct patch paths", () => {
    const s = createStore()
    const recorder1 = recordPatches(s)
    const recorder2 = recordPatches(s.boxes)
    const recorder3 = recordPatches(s.boxes.get("cc")!)
    s.arrows[0].from.x += 117
    expect(recorder1.patches).toEqual([{ op: "replace", path: "/boxes/cc/x", value: 217 }])
    expect(recorder2.patches).toEqual([{ op: "replace", path: "/cc/x", value: 217 }])
    expect(recorder3.patches).toEqual([{ op: "replace", path: "/x", value: 217 }])
})
test("box operations works correctly", () => {
    const s = createStore()
    s.createBox("a", "A", 0, 0, null, null)
    s.createBox("b", "B", 100, 100, s.boxes.get("aa"), "aa2b")
    expect(getSnapshot(s)).toEqual({
        boxes: {
            cc: { id: "cc", name: "Rotterdam", x: 100, y: 100 },
            aa: { id: "aa", name: "Bratislava", x: 650, y: 300 },
            a: { id: "a", name: "A", x: 0, y: 0 },
            b: { id: "b", name: "B", x: 100, y: 100 }
        },
        arrows: [
            { id: "dd", from: "cc", to: "aa" },
            { id: "aa2b", from: "aa", to: "b" }
        ],
        selection: "b"
    })
    s.boxes.get("a")!.setName("I'm groot")
    expect(getSnapshot(s)).toEqual({
        boxes: {
            cc: { id: "cc", name: "Rotterdam", x: 100, y: 100 },
            aa: { id: "aa", name: "Bratislava", x: 650, y: 300 },
            a: { id: "a", name: "I'm groot", x: 0, y: 0 },
            b: { id: "b", name: "B", x: 100, y: 100 }
        },
        arrows: [
            { id: "dd", from: "cc", to: "aa" },
            { id: "aa2b", from: "aa", to: "b" }
        ],
        selection: "b"
    })
    expect(JSON.stringify(s)).toEqual(JSON.stringify(getSnapshot(s)))
    s.boxes.get("a")!.move(50, 50)
    expect(getSnapshot(s)).toEqual({
        boxes: {
            cc: { id: "cc", name: "Rotterdam", x: 100, y: 100 },
            aa: { id: "aa", name: "Bratislava", x: 650, y: 300 },
            a: { id: "a", name: "I'm groot", x: 50, y: 50 },
            b: { id: "b", name: "B", x: 100, y: 100 }
        },
        arrows: [
            { id: "dd", from: "cc", to: "aa" },
            { id: "aa2b", from: "aa", to: "b" }
        ],
        selection: "b"
    })
    expect(s.boxes.get("b")!.width).toBe(15)
    expect(Box.create({ id: "hello" }).isSelected).toBe(false)
})


================================================
FILE: __tests__/core/circular1.test.ts
================================================
import { types } from "../../src"
import { LateTodo2, LateStore2 } from "./circular2.test"
import { expect, test } from "bun:test"
// combine function hosting with types.late to support circular refs between files!
export function LateStore1() {
    return types.model({
        todo: types.late(LateTodo2)
    })
}
export function LateTodo1() {
    return types.model({
        done: types.boolean
    })
}

test("circular test 1 should work", () => {
    const Store1 = types.late(LateStore1)
    const Store2 = types.late(LateStore2)
    expect(Store1.is({})).toBe(false)
    expect(Store1.is({ todo: { done: true } })).toBe(true)
    const s1 = Store1.create({ todo: { done: true } })
    expect(s1.todo.done).toBe(true)
    expect(Store2.is({})).toBe(false)
    expect(Store2.is({ todo: { done: true } })).toBe(true)
    const s2 = Store2.create({ todo: { done: true } })
    expect(s2.todo.done).toBe(true)
})


================================================
FILE: __tests__/core/circular2.test.ts
================================================
import { types } from "../../src"
import { LateTodo1, LateStore1 } from "./circular1.test"
import { expect, test } from "bun:test"
// combine function hosting with types.late to support circular refs between files!
export function LateTodo2() {
    return types.model({
        done: types.boolean
    })
}
export function LateStore2() {
    return types.model({
        todo: types.late(LateTodo1)
    })
}

test("circular test 2 should work", () => {
    const Store1 = types.late(LateStore1)
    const Store2 = types.late(LateStore2)
    expect(Store1.is({})).toBe(false)
    expect(Store1.is({ todo: { done: true } })).toBe(true)
    const s1 = Store1.create({ todo: { done: true } })
    expect(s1.todo.done).toBe(true)
    expect(Store2.is({})).toBe(false)
    expect(Store2.is({ todo: { done: true } })).toBe(true)
    const s2 = Store2.create({ todo: { done: true } })
    expect(s2.todo.done).toBe(true)
})


================================================
FILE: __tests__/core/custom-type.test.ts
================================================
import {
    types,
    recordPatches,
    onSnapshot,
    unprotect,
    applySnapshot,
    applyPatch,
    SnapshotOut
} from "../../src"
import { expect, jest, test } from "bun:test"

class Decimal {
    public number: number
    public fraction: number

    constructor(value: string) {
        const parts = value.split(".")
        this.number = Number(parts[0])
        this.fraction = Number(parts[1])
    }

    toNumber() {
        return this.number + Number("0." + this.fraction)
    }

    toString() {
        return `${this.number}.${this.fraction}`
    }
}

{
    const DecimalPrimitive = types.custom<string, Decimal>({
        name: "Decimal",
        fromSnapshot(value: string, env: any) {
            if (env && env.test) env.test(value)
            return new Decimal(value)
        },
        toSnapshot(value: Decimal) {
            return value.toString()
        },
        isTargetType(value: string | Decimal): value is Decimal {
            return value instanceof Decimal
        },
        getValidationMessage(value: string): string {
            if (/^-?\d+\.\d+$/.test(value)) return "" // OK
            return `'${value}' doesn't look like a valid decimal number`
        }
    })

    const Wallet = types.model({
        balance: DecimalPrimitive,
        lastTransaction: types.maybeNull(DecimalPrimitive)
    })

    test("it should allow for custom primitive types", () => {
        const w1 = Wallet.create({
            balance: new Decimal("2.5")
        })

        expect(w1.balance.number).toBe(2)
        expect(w1.balance.fraction).toBe(5)

        const w2 = Wallet.create({ balance: "3.5" })
        expect(w2.balance.number).toBe(3)
        expect(w2.balance.fraction).toBe(5)

        if (process.env.NODE_ENV !== "production")
            expect(() => Wallet.create({ balance: "two point one" })).toThrow(
                "(Invalid value for type 'Decimal': 'two point one' doesn't look like a valid decimal number)"
            )
    })

    // test reassignment / reconcilation / conversion works
    test("reassignments will work", () => {
        const w1 = Wallet.create({ balance: "2.5" })
        unprotect(w1)

        const p = recordPatches(w1)
        const snapshots: SnapshotOut<typeof Wallet>[] = []
        onSnapshot(w1, s => {
            snapshots.push(s)
        })

        const b1 = w1.balance
        expect(b1).toBeInstanceOf(Decimal)

        w1.balance = "2.5" as any // TODO: make cast work with custom types
        expect(b1).toBeInstanceOf(Decimal)
        expect(w1.balance).toBe(b1) // reconciled

        w1.balance = new Decimal("2.5") // not reconciling! // TODO: introduce custom hook for that?
        expect(b1).toBeInstanceOf(Decimal)

        w1.balance = new Decimal("3.5")
        expect(b1).toBeInstanceOf(Decimal)

        w1.balance = "4.5" as any
        expect(b1).toBeInstanceOf(Decimal)

        w1.lastTransaction = b1
        expect(w1.lastTransaction).toBe(b1)

        w1.lastTransaction = null
        expect(w1.lastTransaction).toBe(null)

        // patches & snapshots
        expect(snapshots).toMatchSnapshot()
        p.stop()
        expect(p.patches).toMatchSnapshot()
    })

    test("passes environment to fromSnapshot", () => {
        const env = { test: jest.fn() }
        Wallet.create({ balance: "3.0" }, env)
        expect(env.test).toHaveBeenCalledWith("3.0")
    })
}

{
    test("complex representation", () => {})

    const DecimalTuple = types.custom<[number, number], Decimal>({
        name: "DecimalTuple",
        fromSnapshot(value: [number, number]) {
            return new Decimal(value[0] + "." + value[1])
        },
        toSnapshot(value: Decimal) {
            return [value.number, value.fraction]
        },
        isTargetType(value: [number, number] | Decimal): value is Decimal {
            return value instanceof Decimal
        },
        getValidationMessage(value: [number, number]): string {
            if (Array.isArray(value) && value.length === 2) return "" // OK
            return `'${JSON.stringify(value)}' doesn't look like a valid decimal number`
        }
    })

    const Wallet = types.model({ balance: DecimalTuple })

    test("it should allow for complex custom primitive types", () => {
        const w1 = Wallet.create({
            balance: new Decimal("2.5")
        })

        expect(w1.balance.number).toBe(2)
        expect(w1.balance.fraction).toBe(5)

        const w2 = Wallet.create({ balance: [3, 5] })
        expect(w2.balance.number).toBe(3)
        expect(w2.balance.fraction).toBe(5)

        if (process.env.NODE_ENV !== "production")
            expect(() => Wallet.create({ balance: "two point one" } as any)).toThrow(
                "(Invalid value for type 'DecimalTuple': '\"two point one\"' doesn't look like a valid decimal number)"
            )
    })

    // test reassignment / reconcilation / conversion works
    test("complex reassignments will work", () => {
        const w1 = Wallet.create({ balance: [2, 5] })
        unprotect(w1)

        const p = recordPatches(w1)
        const snapshots: SnapshotOut<typeof Wallet>[] = []
        onSnapshot(w1, s => {
            snapshots.push(s)
        })

        const b1 = w1.balance
        expect(b1).toBeInstanceOf(Decimal)

        w1.balance = [2, 5] as any
        expect(b1).toBeInstanceOf(Decimal)
        expect(w1.balance).not.toBe(b1) // not reconciled, balance is not deep equaled (TODO: future feature?)

        w1.balance = new Decimal("2.5") // not reconciling!
        expect(b1).toBeInstanceOf(Decimal)

        w1.balance = new Decimal("3.5")
        expect(b1).toBeInstanceOf(Decimal)

        w1.balance = [4, 5] as any
        expect(b1).toBeInstanceOf(Decimal)

        // patches & snapshots
        expect(snapshots).toMatchSnapshot()
        p.stop()
        expect(p.patches).toMatchSnapshot()
    })

    test("can apply snapshot and patch", () => {
        const w1 = Wallet.create({ balance: [3, 0] })
        applySnapshot(w1, { balance: [4, 5] })
        expect(w1.balance).toBeInstanceOf(Decimal)
        expect(w1.balance.toString()).toBe("4.5")

        applyPatch(w1, {
            op: "replace",
            path: "/balance",
            value: [5, 0]
        })
        expect(w1.balance.toString()).toBe("5.0")
    })
}


================================================
FILE: __tests__/core/date.test.ts
================================================
import { t } from "../../src"
import { Hook, NodeLifeCycle } from "../../src/internal"
import { describe, expect, it, test } from "bun:test"

describe("types.date", () => {
    describe("methods", () => {
        describe("create", () => {
            describe("with no arguments", () => {
                if (process.env.NODE_ENV !== "production") {
                    it("should throw an error in development", () => {
                        expect(() => {
                            t.Date.create()
                        }).toThrow()
                    })
                }
            })
            describe("with a number argument", () => {
                it("should return a Date object", () => {
                    const d = t.Date.create(1701369873059)
                    expect(d instanceof Date).toBe(true)
                })
            })
            describe("with a Date argument", () => {
                it("should return a Date object", () => {
                    const input = new Date()
                    const d = t.Date.create(input)
                    expect(d instanceof Date).toBe(true)
                })
            })
        })
        describe("with argument of different types", () => {
            const testCases = [
                null,
                undefined,
                true,
                [],
                function () {},
                "2022-01-01T00:00:00.000Z",
                /a/,
                new Map(),
                new Set(),
                Symbol(),
                new Error()
            ]

            if (process.env.NODE_ENV !== "production") {
                testCases.forEach(testCase => {
                    it(`should throw an error when passed ${JSON.stringify(testCase)}`, () => {
                        expect(() => {
                            t.Date.create(testCase as any)
                        }).toThrow()
                    })
                })
            }
        })
    })
    describe("describe", () => {
        it("should return the value 'Date'", () => {
            const description = t.Date.describe()
            expect(description).toBe("Date")
        })
    })
    describe("getSnapshot", () => {
        it("should return a number from a date", () => {
            const date = new Date("2022-01-01T00:00:00.000Z")
            const d = t.Date.instantiate(null, "", {}, date)
            const snapshot = t.Date.getSnapshot(d)
            expect(snapshot).toBe(1640995200000)
        })
        it("should return a number from a number", () => {
            const d = t.Date.instantiate(null, "", {}, 1701369873059)
            const snapshot = t.Date.getSnapshot(d)
            expect(snapshot).toBe(1701369873059)
        })
    })
    describe("getSubtype", () => {
        it("should return null", () => {
            const subtype = t.Date.getSubTypes()
            expect(subtype).toBe(null)
        })
    })
    describe("instantiate", () => {
        if (process.env.NODE_ENV !== "production") {
            describe("with invalid arguments", () => {
                it("should not throw an error", () => {
                    expect(() => {
                        // @ts-ignore
                        t.Date.instantiate()
                    }).not.toThrow()
                })
            })
        }
        describe("with a Date argument", () => {
            it("should return an object", () => {
                const s = t.Date.instantiate(null, "", {}, new Date())
                expect(typeof s).toBe("object")
            })
        })
        describe("with a number argument", () => {
            it("should return an object", () => {
                const s = t.Date.instantiate(null, "", {}, 1701369873059)
                expect(typeof s).toBe("object")
            })
        })
    })
    describe("is", () => {
        describe("with a Date argument", () => {
            it("should return true", () => {
                const result = t.Date.is(new Date())
                expect(result).toBe(true)
            })
        })
        describe("with a number argument", () => {
            it("should return true", () => {
                const result = t.Date.is(1701369873059)
                expect(result).toBe(true)
            })
        })
        describe("with argument of different types", () => {
            const testCases = [
                null,
                undefined,
                true,
                [],
                function () {},
                "2022-01-01T00:00:00.000Z",
                /a/,
                new Map(),
                new Set(),
                Symbol(),
                new Error()
            ]

            testCases.forEach(testCase => {
                it(`should return false when passed ${JSON.stringify(testCase)}`, () => {
                    const result = t.Date.is(testCase as any)
                    expect(result).toBe(false)
                })
            })
        })
    })
    describe("isAssignableFrom", () => {
        describe("with a Date argument", () => {
            it("should return true", () => {
                const result = t.Date.isAssignableFrom(t.Date)
                expect(result).toBe(true)
            })
        })
        describe("with argument of different types", () => {
            const testCases = [
                t.string,
                t.boolean,
                t.finite,
                t.float,
                t.identifier,
                t.identifierNumber,
                t.integer,
                t.null,
                t.number,
                t.undefined
            ]

            testCases.forEach(testCase => {
                it(`should return false when passed ${JSON.stringify(testCase)}`, () => {
                    const result = t.Date.isAssignableFrom(testCase as any)
                    expect(result).toBe(false)
                })
            })
        })

        // TODO: we need to test this, but to be honest I'm not sure what the expected behavior is on single date nodes.
        describe.skip("reconcile", () => {})
        describe("validate", () => {
            describe("with a Date argument", () => {
                it("should return with no validation errors", () => {
                    const result = t.Date.validate(new Date(), [])
                    expect(result).toEqual([])
                })
            })
            describe("with a number argument", () => {
                it("should return with no validation errors", () => {
                    const result = t.Date.validate(1701369873059, [])
                    expect(result).toEqual([])
                })
            })
            describe("with argument of different types", () => {
                const testCases = [
                    null,
                    undefined,
                    "2022-01-01T00:00:00.000Z",
                    true,
                    [],
                    function () {},
                    /a/,
                    new Map(),
                    new Set(),
                    Symbol(),
                    new Error()
                ]

                testCases.forEach(testCase => {
                    it(`should return with a validation error when passed ${JSON.stringify(
                        testCase
                    )}`, () => {
                        const result = t.Date.validate(testCase as any, [])
                        expect(result).toEqual([
                            {
                                context: [],
                                message: "Value is not a Date or a unix milliseconds timestamp",
                                value: testCase
                            }
                        ])
                    })
                })
            })
        })
    })
    describe("properties", () => {
        describe("flags", () => {
            test("return the correct value", () => {
                const flags = t.Date.flags
                expect(flags).toBe(8)
            })
        })

        describe("identifierAttribute", () => {
            // We don't have a way to set the identifierAttribute on a primitive type, so this should return undefined.
            test("returns undefined", () => {
                const identifierAttribute = t.Date.identifierAttribute
                expect(identifierAttribute).toBeUndefined()
            })
        })
        describe("isType", () => {
            test("returns true", () => {
                const isType = t.Date.isType
                expect(isType).toBe(true)
            })
        })
        describe("name", () => {
            test('returns "Date"', () => {
                const name = t.Date.name
                expect(name).toBe("Date")
            })
        })
    })
    describe("instance", () => {
        describe("methods", () => {
            describe("aboutToDie", () => {
                it("calls the beforeDetach hook", () => {
                    const d = t.Date.instantiate(null, "", {}, new Date())
                    let called = false
                    d.registerHook(Hook.beforeDestroy, () => {
                        called = true
                    })
                    d.aboutToDie()
                    expect(called).toBe(true)
                })
            })
            describe("die", () => {
                it("kills the node", () => {
                    const d = t.Date.instantiate(null, "", {}, new Date())
                    d.die()
                    expect(d.isAlive).toBe(false)
                })
                it("should mark the node as dead", () => {
                    const d = t.Date.instantiate(null, "", {}, new Date())
                    d.die()
                    expect(d.state).toBe(NodeLifeCycle.DEAD)
                })
            })
            describe("finalizeCreation", () => {
                it("should mark the node as finalized", () => {
                    const d = t.Date.instantiate(null, "", {}, new Date())
                    d.finalizeCreation()
                    expect(d.state).toBe(NodeLifeCycle.FINALIZED)
                })
            })
            describe("finalizeDeath", () => {
                it("should mark the node as dead", () => {
                    const d = t.Date.instantiate(null, "", {}, new Date())
                    d.finalizeDeath()
                    expect(d.state).toBe(NodeLifeCycle.DEAD)
                })
            })
            describe("getReconciliationType", () => {
                it("should return the correct type", () => {
                    const d = t.Date.instantiate(null, "", {}, new Date())
                    const type = d.getReconciliationType()
                    expect(type).toBe(t.Date)
                })
            })
            describe("getSnapshot", () => {
                it("should return the value passed in with a number", () => {
                    const d = t.Date.instantiate(null, "", {}, 1701373349399)
                    const snapshot = d.getSnapshot()
                    expect(snapshot).toBe(1701373349399)
                })

                it("should return the correct date getTime value with a date object", () => {
                    const date = new Date("2022-01-01T00:00:00.000Z")
                    const d = t.Date.instantiate(null, "", {}, date)
                    const snapshot = d.getSnapshot()
                    const expected = date.getTime()
                    expect(snapshot).toBe(expected)
                })
            })
            describe("registerHook", () => {
                it("should register a hook and call it", () => {
                    const d = t.Date.instantiate(null, "", {}, new Date())
                    let called = false
                    d.registerHook(Hook.beforeDestroy, () => {
                        called = true
                    })

                    d.die()

                    expect(called).toBe(true)
                })
            })
            describe("setParent", () => {
                if (process.env.NODE_ENV !== "production") {
                    describe("with null", () => {
                        it("should throw an error", () => {
                            const d = t.Date.instantiate(null, "", {}, new Date())
                            expect(() => {
                                d.setParent(null, "foo")
                            }).toThrow()
                        })
                    })
                    describe("with a parent object", () => {
                        it("should throw an error", () => {
                            const Parent = t.model({
                                child: t.Date
                            })

                            const parent = Parent.create({ child: new Date() })

                            const d = t.Date.instantiate(null, "", {}, new Date())

                            expect(() => {
                                // @ts-ignore
                                d.setParent(parent, "bar")
                            }).toThrow(
                                "[mobx-state-tree] assertion failed: scalar nodes cannot change their parent"
                            )
                        })
                    })
                }
            })
        })
    })
})


================================================
FILE: __tests__/core/deprecated.test.ts
================================================
import { deprecated } from "../../src/utils"
import { flow, createFlowSpawner } from "../../src/core/flow"
import { process as mstProcess, createProcessSpawner } from "../../src/core/process"
import { expect, jest, test } from "bun:test"

function createDeprecationListener() {
    // clear previous deprecation dedupe keys
    deprecated.ids = {}
    // save console.warn native implementation
    const originalWarn = console.warn
    // create spy to track warning call
    const spyWarn = (console.warn = jest.fn())
    // return callback to check if warn was called properly
    return function isDeprecated() {
        // replace original implementation
        console.warn = originalWarn
        // test for correct log message, if in development
        if (process.env.NODE_ENV !== "production") {
            expect(spyWarn).toHaveBeenCalledTimes(1)
            expect(spyWarn.mock.calls[0][0].message).toMatch(/Deprecation warning:/)
        }
    }
}
test("`process` should mirror `flow`", () => {
    const isDeprecated = createDeprecationListener()
    const generator = function* () {}
    const flowResult = flow(generator)
    const processResult = mstProcess(generator)
    expect(processResult.name).toBe(flowResult.name)
    isDeprecated()
})
test("`createProcessSpawner` should mirror `createFlowSpawner`", () => {
    const isDeprecated = createDeprecationListener()
    const alias = "generatorAlias"
    const generator = function* (): IterableIterator<void> {}
    const flowSpawnerResult = createFlowSpawner(alias, generator)
    const processSpawnerResult = createProcessSpawner(alias, generator)
    expect(processSpawnerResult.name).toBe(flowSpawnerResult.name)
    isDeprecated()
})


================================================
FILE: __tests__/core/enum.test.ts
================================================
import { types, unprotect } from "../../src"
import { expect, test } from "bun:test"

enum ColorEnum {
    Red = "Red",
    Orange = "Orange",
    Green = "Green"
}
const colorEnumValues = Object.values(ColorEnum) as ColorEnum[]

test("should support enums", () => {
    const TrafficLight = types.model({ color: types.enumeration("Color", colorEnumValues) })
    expect(TrafficLight.is({ color: ColorEnum.Green })).toBe(true)
    expect(TrafficLight.is({ color: "Blue" })).toBe(false)
    expect(TrafficLight.is({ color: undefined })).toBe(false)
    const l = TrafficLight.create({ color: ColorEnum.Orange })
    unprotect(l)
    l.color = ColorEnum.Red
    expect(TrafficLight.describe()).toBe('{ color: ("Red" | "Orange" | "Green") }')
    if (process.env.NODE_ENV !== "production") {
        expect(() => (l.color = "Blue" as any)).toThrow(
            /Error while converting `"Blue"` to `Color`/
        )
    }
})
test("should support anonymous enums", () => {
    const TrafficLight = types.model({ color: types.enumeration(colorEnumValues) })
    const l = TrafficLight.create({ color: ColorEnum.Orange })
    unprotect(l)
    l.color = ColorEnum.Red
    expect(TrafficLight.describe()).toBe('{ color: ("Red" | "Orange" | "Green") }')
    if (process.env.NODE_ENV !== "production") {
        expect(() => (l.color = "Blue" as any)).toThrow(
            /Error while converting `"Blue"` to `"Red" | "Orange" | "Green"`/
        )
    }
})
test("should support optional enums", () => {
    const TrafficLight = types.optional(types.enumeration(colorEnumValues), ColorEnum.Orange)
    const l = TrafficLight.create()
    expect(l).toBe(ColorEnum.Orange)
})
test("should support optional enums inside a model", () => {
    const TrafficLight = types.model({
        color: types.optional(types.enumeration(colorEnumValues), ColorEnum.Orange)
    })
    const l = TrafficLight.create({})
    expect(l.color).toBe(ColorEnum.Orange)
})
test("should support plain string[] arrays", () => {
    const colorOptions: string[] = ["Red", "Orange", "Green"]
    const TrafficLight = types.model({ color: types.enumeration(colorOptions) })
    const l = TrafficLight.create({ color: "Orange" })
    unprotect(l)
    l.color = "Red"
    expect(TrafficLight.describe()).toBe('{ color: ("Red" | "Orange" | "Green") }')
    if (process.env.NODE_ENV !== "production") {
        expect(() => (l.color = "Blue" as any)).toThrow(
            /Error while converting `"Blue"` to `"Red" | "Orange" | "Green"`/
        )
    }
})
test("should support readonly enums as const", () => {
    const colorOptions = ["Red", "Orange", "Green"] as const
    const TrafficLight = types.model({ color: types.enumeration(colorOptions) })
    const l = TrafficLight.create({ color: "Orange" })
    unprotect(l)
    l.color = "Red"
    expect(TrafficLight.describe()).toBe('{ color: ("Red" | "Orange" | "Green") }')
    if (process.env.NODE_ENV !== "production") {
        expect(() => (l.color = "Blue" as any)).toThrow(
            /Error while converting `"Blue"` to `"Red" | "Orange" | "Green"`/
        )
    }
})


================================================
FILE: __tests__/core/env.test.ts
================================================
import { configure } from "mobx"
import {
    types,
    hasEnv,
    getEnv,
    clone,
    detach,
    unprotect,
    walk,
    getPath,
    castToSnapshot,
    hasParent,
    Instance,
    destroy,
    getParent,
    IAnyStateTreeNode,
    isStateTreeNode,
    isAlive
} from "../../src"
import { expect, test } from "bun:test"

// tslint:disable: no-unused-expression

const Todo = types
    .model({
        title: "test"
    })
    .views(self => ({
        get description() {
            return getEnv(self).useUppercase ? self.title.toUpperCase() : self.title
        }
    }))
const Store = types.model({
    todos: types.array(Todo)
})

function createEnvironment() {
    return {
        useUppercase: true
    }
}

test("it should be possible to use environments", () => {
    const env = createEnvironment()
    const todo = Todo.create({}, env)
    expect(hasEnv(todo)).toBe(true)
    expect(todo.description).toBe("TEST")
    env.useUppercase = false
    expect(todo.description).toBe("test")
})
test("it should be possible to inherit environments", () => {
    const env = createEnvironment()
    const store = Store.create({ todos: [{}] }, env)
    expect(hasEnv(store.todos[0])).toBe(true)
    expect(store.todos[0].description).toBe("TEST")
    env.useUppercase = false
    expect(store.todos[0].description).toBe("test")
})
test("getEnv throws error without environment", () => {
    const todo = Todo.create()
    expect(hasEnv(todo)).toBe(false)
    expect(() => getEnv(todo)).toThrow("Failed to find the environment of AnonymousModel@<root>")
})
test("detach should preserve environment", () => {
    const env = createEnvironment()
    const store = Store.create({ todos: [{}] }, env)
    unprotect(store)
    const todo = detach(store.todos[0])
    expect(hasEnv(todo)).toBe(true)
    expect(todo.description).toBe("TEST")
    env.useUppercase = false
    expect(todo.description).toBe("test")
})
test("it is possible to assign instance with the same environment as the parent to a tree", () => {
    const env = createEnvironment()
    const store = Store.create({ todos: [] }, env)
    const todo = Todo.create({}, env)
    unprotect(store)
    store.todos.push(todo)
    expect(store.todos.length === 1).toBe(true)
    expect(getEnv(store.todos) === getEnv(store.todos[0])).toBe(true)
    expect(getEnv(todo) === getEnv(store.todos[0])).toBe(true)
})
test("it is not possible to assign instance with a different environment than the parent to a tree", () => {
    if (process.env.NODE_ENV !== "production") {
        const env1 = createEnvironment()
        const env2 = createEnvironment()
        const store = Store.create({ todos: [] }, env1)
        const todo = Todo.create({}, env2)
        unprotect(store)
        expect(() => store.todos.push(todo)).toThrow(
            "[mobx-state-tree] A state tree cannot be made part of another state tree as long as their environments are different."
        )
    }
})
test("it is possible to set a value inside a map of a map when using the same environment", () => {
    const env = createEnvironment()
    const EmptyModel = types.model({})
    const MapOfEmptyModel = types.model({
        map: types.map(EmptyModel)
    })
    const MapOfMapOfEmptyModel = types.model({
        map: types.map(MapOfEmptyModel)
    })
    const mapOfMap = MapOfMapOfEmptyModel.create(
        {
            map: {
                whatever: {
                    map: {}
                }
            }
        },
        env
    )
    unprotect(mapOfMap)
    // this should not throw
    mapOfMap.map.get("whatever")!.map.set("1234", EmptyModel.create({}, env))
    expect(getEnv(mapOfMap) === env).toBe(true)
    expect(getEnv(mapOfMap.map.get("whatever")!.map.get("1234")!) === env).toBe(true)
})
test("clone preserves environment", () => {
    const env = createEnvironment()
    const store = Store.create({ todos: [{}] }, env)
    {
        const todo = clone(store.todos[0])

        expect(getEnv(todo) === env).toBe(true)
    }
    {
        const todo = clone(store.todos[0], true)
        expect(getEnv(todo) === env).toBe(true)
        expect(getEnv(todo) === env).toBe(true)
    }
    {
        const todo = clone(store.todos[0], false)
        expect(hasEnv(todo)).toBe(false)
        expect(() => {
            getEnv(todo)
        }).toThrow("Failed to find the environment of AnonymousModel@<root>")
    }
    {
        const env2 = createEnvironment()
        const todo = clone(store.todos[0], env2)
        expect(env2 === getEnv(todo)).toBe(true)
    }
})

test("#1231", () => {
    configure({
        useProxies: "never"
    })

    const envObj = createEnvironment()
    const logs: string[] = []

    function nofParents(node: IAnyStateTreeNode) {
        let parents = 0
        let parent = node
        while (hasParent(parent)) {
            parents++
            parent = getParent(parent)
        }
        return parents
    }

    function leafsFirst(root: IAnyStateTreeNode) {
        const nodes: IAnyStateTreeNode[] = []
        walk(root, i => {
            if (isStateTreeNode(i)) {
                nodes.push(i)
            }
        })
        // sort by number of parents
        nodes.sort((a, b) => {
            return nofParents(b) - nofParents(a)
        })
        return nodes
    }

    function check(root: Instance<typeof RS>, name: string, mode: "detach" | "destroy") {
        function logFail(operation: string, n: any) {
            logs.push(`fail: (${name}) ${operation}: ${getPath(n)}, ${n}`)
        }
        function log(operation: string, n: any) {
            logs.push(`ok: (${name}) ${operation}: ${getPath(n)}, ${n}`)
        }

        // make sure all nodes are there
        root.s1.arr[0].title
        root.s1.m.get("one")!.title
        root.s2
        const nodes = leafsFirst(root)
        expect(nodes.length).toBe(7)

        nodes.forEach(i => {
            const env = getEnv(i)
            const parent = hasParent(i)
            if (!parent && i !== root) {
                logFail("expected a parent, but none found", i)
            } else {
                log("had parent or was root", i)
            }
            if (env !== envObj) {
                logFail("expected same env as root, but was different", i)
            } else {
                log("same env as root", i)
            }
        })

        unprotect(root)
        nodes.forEach(i => {
            const optional = optionalPaths.includes(getPath(i))
            if (mode === "detach") {
                log("detaching node", i)
                detach(i)
            } else {
                log("destroying node", i)
                destroy(i)
            }
            const env = hasEnv(i) ? getEnv(i) : undefined
            const parent = hasParent(i)
            const alive = isAlive(i)
            if (mode === "detach") {
                if (parent) {
                    logFail(`expected no parent after detach, but one was found`, i)
                } else {
                    log(`no parent after detach`, i)
                }
                if (env !== envObj) {
                    logFail("expected same env as root after detach, but it was not", i)
                } else {
                    log("env kept after detach", i)
                }
                if (!alive) {
                    logFail("expected to be alive after detach, but it was not", i)
                } else {
                    log("alive after detach", i)
                }
            } else {
                // destroy might or might not keep the env, but doesn't matter so we don't check
                if (optional) {
                    // optional (undefined) nodes will be assigned undefined and reconciled, therefore they will be kept alive
                    if (!parent) {
                        logFail(
                            `expected a parent after destroy (since it is optional), but none was found`,
                            i
                        )
                    } else {
                        log(`had parent after destroy (since it is optional)`, i)
                    }
                    if (!alive) {
                        logFail(
                            "expected to be alive after destroy (since it is optional), but it was not",
                            i
                        )
                    } else {
                        log("alive after destroy (since it is optional)", i)
                    }
                } else {
                    if (parent) {
                        logFail(`expected no parent after destroy, but one was found`, i)
                    } else {
                        log(`no parent after destroy`, i)
                    }
                    if (alive) {
                        logFail("expected to be dead after destroy, but it was not", i)
                    } else {
                        log("dead after destroy", i)
                    }
                }
            }
        })
    }

    const T = types.model("T", { title: "some title" })

    const S1Arr = types.array(T)
    const S1Map = types.map(T)
    const S1 = types.model("S1", {
        arr: S1Arr,
        m: S1Map
    })

    const S2 = types.model("S2", {})

    const RS = types.model("RS", {
        s1: types.optional(S1, {}),
        s2: types.optional(S2, {})
    })

    const optionalPaths = ["/s1", "/s2", "/s1/m", "/s1/arr"]

    const data = {
        s1: castToSnapshot(
            S1.create({
                arr: S1Arr.create([T.create({})]),
                m: castToSnapshot(S1Map.create({ one: T.create({}) }))
            })
        ),
        s2: S2.create()
    }
    const rsCreate = RS.create(data, envObj)
    const rsCreate2 = clone(rsCreate, true)

    const rsSnap = RS.create(
        {
            s1: {
                arr: [{}],
                m: { one: {} }
            },
            s2: {}
        },
        envObj
    )
    const rsSnap2 = clone(rsCreate, true)

    check(rsCreate, "using create", "detach")
    check(rsSnap, "using snapshot", "detach")
    check(rsCreate2, "using create", "destroy")
    check(rsSnap2, "using snapshot", "destroy")

    const fails = logs.filter(l => l.startsWith("fail:"))
    if (fails.length > 0) {
        expect().fail(`\n${fails.join("\n")}`)
    }
})


================================================
FILE: __tests__/core/frozen.test.ts
================================================
import { getSnapshot, types, unprotect } from "../../src"
import { expect, test } from "bun:test"

test("it should accept any serializable value", () => {
    const Factory = types.model({
        value: types.frozen<{ a: number; b: number } | undefined>()
    })
    const doc = Factory.create()
    unprotect(doc)
    doc.value = { a: 1, b: 2 }
    expect(getSnapshot(doc)).toEqual({ value: { a: 1, b: 2 } })
})

if (process.env.NODE_ENV !== "production") {
    test("it should throw if value is not serializable", () => {
        const Factory = types.model({
            value: types.frozen<Function | undefined>()
        })
        const doc = Factory.create()
        unprotect(doc)
        expect(() => {
            doc.value = function IAmUnserializable() {}
        }).toThrow(/Error while converting <function IAmUnserializable> to `frozen`/)
    })
}

test("it should accept any default value value", () => {
    const Factory = types.model({
        value: types.frozen(3)
    })
    const doc = Factory.create()
    expect(Factory.is({})).toBeTruthy()
    expect(getSnapshot(doc)).toEqual({ value: 3 })
})

test("it should type strongly", () => {
    type Point = { x: number; y: number }
    const Mouse = types
        .model({
            loc: types.frozen<Point>()
        })
        .actions(self => ({
            moveABit() {
                // self.loc.x += 1; // compile error, x is readonly!
                ;(self.loc as any).x += 1 // throws, frozen!
            }
        }))

    expect(Mouse.is({})).toBeTruthy() // any value is acceptable to frozen, even undefined...

    const m = Mouse.create({
        // loc: 3 // type error!
        loc: { x: 2, y: 3 }
    })

    if (process.env.NODE_ENV !== "production") {
        expect(() => {
            m.moveABit()
        }).toThrow("Attempted to assign to readonly property.")
    }
})

if (process.env.NODE_ENV !== "production") {
    test("it should be capable of using another MST type", () => {
        const Point = types.model("Point", { x: types.number, y: types.number })
        const Mouse = types.model({
            loc: types.frozen(Point)
        })

        expect(Mouse.is({})).toBeFalsy()
        expect(Mouse.is({ loc: {} })).toBeFalsy()
        expect(Mouse.is({ loc: { x: 3, y: 2 } })).toBeTruthy()

        expect(() => {
            ;(Mouse.create as any)()
        }).toThrow(
            'at path "/loc" value `undefined` is not assignable to type: `frozen(Point)` (Value is not a plain object)'
        )
        expect(() => {
            Mouse.create({ loc: { x: 4 } } as any)
        }).toThrow(
            'at path "/loc/y" value `undefined` is not assignable to type: `number` (Value is not a number)'
        )

        const m = Mouse.create({
            loc: { x: 3, y: 2 }
        })

        const x = m.loc.x
        expect(x).toBe(3)
    })
}


================================================
FILE: __tests__/core/hooks.test.ts
================================================
import {
    addDisposer,
    destroy,
    detach,
    types,
    unprotect,
    getSnapshot,
    applySnapshot,
    onSnapshot,
    isAlive,
    hasParent,
    cast,
    resolvePath,
    getParent
} from "../../src"
import { expect, jest, test } from "bun:test"

function createTestStore(listener: (s: string) => void) {
    const Todo = types
        .model("Todo", {
            title: ""
        })
        .actions(self => {
            function afterCreate() {
                listener("new todo: " + self.title)
                addDisposer(self, () => {
                    listener("custom disposer 1 for " + self.title)
                })
                addDisposer(self, () => {
                    listener("custom disposer 2 for " + self.title)
                })
            }
            function beforeDestroy() {
                listener("destroy todo: " + self.title)
            }
            function afterAttach() {
                listener("attach todo: " + self.title)
            }
            function beforeDetach() {
                listener("detach todo: " + self.title)
            }
            return {
                afterCreate,
                beforeDestroy,
                afterAttach,
                beforeDetach
            }
        })
    const Store = types
        .model("Store", {
            todos: types.array(Todo)
        })
        .actions(self => {
            function afterCreate() {
                unprotect(self)
                listener("new store: " + self.todos.length)
                addDisposer(self, () => {
                    listener("custom disposer for store")
                })
            }
            function beforeDestroy() {
                listener("destroy store: " + self.todos.length)
            }
            return {
                afterCreate,
                beforeDestroy
            }
        })
    return {
        store: Store.create({
            todos: [{ title: "Get coffee" }, { title: "Get biscuit" }, { title: "Give talk" }]
        }),
        Store,
        Todo
    }
}

// NOTE: as we defer creation (and thus, hooks) till first real access,
// some of original hooks do not fire at all
test("it should trigger lifecycle hooks", () => {
    const events: string[] = []
    // new store: 3
    const { store, Todo } = createTestStore(e => events.push(e))

    events.push("-")
    // access (new, attach), then detach "Give Talk"
    const talk = detach(store.todos[2])
    expect(isAlive(talk)).toBe(true)
    expect(hasParent(talk)).toBe(false)

    events.push("--")

    // access (new, attach), then destroy biscuit
    const oldBiscuit = store.todos.pop()!
    expect(isAlive(oldBiscuit)).toBe(false)

    events.push("---")
    // new and then attach "add sugar"
    const sugar = Todo.create({
        title: "add sugar"
    })
    store.todos.push(sugar)

    events.push("----")
    // destroy elements in the array ("add sugar"), then store
    destroy(store)
    expect(isAlive(store)).toBe(false)

    events.push("-----")
    // destroy "Give talk"
    destroy(talk)
    expect(isAlive(talk)).toBe(false)

    expect(events).toEqual([
        "new store: 3",
        "-",
        "new todo: Give talk",
        "attach todo: Give talk",
        "detach todo: Give talk",
        "--",
        "new todo: Get biscuit",
        "attach todo: Get biscuit",
        "destroy todo: Get biscuit",
        "custom disposer 2 for Get biscuit",
        "custom disposer 1 for Get biscuit",
        "---",
        "new todo: add sugar",
        "attach todo: add sugar",
        "----",
        "destroy todo: add sugar",
        "custom disposer 2 for add sugar",
        "custom disposer 1 for add sugar",
        "destroy store: 2",
        "custom disposer for store",
        "-----",
        "destroy todo: Give talk",
        "custom disposer 2 for Give talk",
        "custom disposer 1 for Give talk"
    ])
})

test("lifecycle hooks can access their children", () => {
    const events: string[] = []
    function listener(e: string) {
        events.push(e)
    }

    const Child = types
        .model("Todo", {
            title: ""
        })
        .actions(self => ({
            afterCreate() {
                listener("new child: " + self.title)
            },
            afterAttach() {
                listener("parent available: " + !!getParent(self))
            }
        }))

    const Parent = types
        .model("Parent", {
            child: Child
        })
        .actions(self => ({
            afterCreate() {
                // **This the key line**: it is trying to access the child
                listener("new parent, child.title: " + self.child?.title)
            }
        }))

    const Store = types.model("Store", {
        parent: types.maybe(Parent)
    })

    const store = Store.create({
        parent: {
            child: { title: "Junior" }
        }
    })
    // As expected no hooks are called.
    // The `parent` is not accessed it is just loaded.
    events.push("-")

    // Simple access does a sensible thing
    const parent = store.parent
    expect(events).toEqual([
        "-",
        "new child: Junior",
        "new parent, child.title: Junior",
        "parent available: true"
    ])

    // Clear the events and make a new store
    events.length = 0
    const store2 = Store.create({
        parent: {
            child: { title: "Junior" }
        }
    })
    events.push("-")

    // Previously resolvePath would cause problems because the parent hooks
    // would be called before the child was fully created
    const child = resolvePath(store2, "/parent/child")
    expect(events).toEqual([
        "-",
        "new child: Junior",
        "new parent, child.title: Junior",
        "parent available: true"
    ])
})

type CarSnapshot = { id: string }
const Car = types
    .model("Car", {
        id: types.number
    })
    .preProcessSnapshot<CarSnapshot>(snapshot =>
        Object.assign({}, snapshot, { id: Number(snapshot.id) * 2 })
    )
    .postProcessSnapshot<CarSnapshot>(snapshot =>
        Object.assign({}, snapshot, { id: "" + snapshot.id / 2 })
    )

const Factory = types.model("Factory", {
    car: Car
})

const Motorcycle = types
    .model("Motorcycle", {
        id: types.string
    })
    .preProcessSnapshot<CarSnapshot>(snapshot =>
        Object.assign({}, snapshot, { id: snapshot.id.toLowerCase() })
    )
    .postProcessSnapshot<CarSnapshot>(snapshot =>
        Object.assign({}, snapshot, { id: snapshot.id.toUpperCase() })
    )
const MotorcycleFactory = types.model("MotorcycleFactory", {
    motorcycles: types.array(Motorcycle)
})

test("it should preprocess snapshots when creating", () => {
    const car = Car.create({ id: "1" })
    expect(car.id).toBe(2)
})
test("it should preprocess snapshots when updating", () => {
    const car = Car.create({ id: "1" })
    expect(car.id).toBe(2)
    applySnapshot(car, { id: "6" })
    expect(car.id).toBe(12)
})
test("it should postprocess snapshots when generating snapshot - 1", () => {
    const car = Car.create({ id: "1" })
    expect(car.id).toBe(2)
    expect(getSnapshot(car)).toEqual({ id: "1" })
})
test("it should not apply postprocessor t
Download .txt
gitextract_v8l79haa/

├── .circleci/
│   └── config.yml
├── .dockerignore
├── .gitattributes
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   └── bug-report.md
│   ├── lock.yml
│   ├── pull_request_template.md
│   └── stale.yml
├── .gitignore
├── .husky/
│   └── pre-commit
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── Dockerfile
├── ISSUE_TEMPLATE.md
├── LICENSE
├── README.md
├── SECURITY.md
├── __tests__/
│   ├── core/
│   │   ├── 1525.test.ts
│   │   ├── 1664.test.ts
│   │   ├── 2230.test.ts
│   │   ├── __snapshots__/
│   │   │   ├── async.test.ts.snap
│   │   │   ├── custom-type.test.ts.snap
│   │   │   └── reference-custom.test.ts.snap
│   │   ├── action.test.ts
│   │   ├── actionTrackingMiddleware2.test.ts
│   │   ├── api.test.ts
│   │   ├── array.test.ts
│   │   ├── async.test.ts
│   │   ├── bigint.test.ts
│   │   ├── boolean.test.ts
│   │   ├── boxes-store.test.ts
│   │   ├── circular1.test.ts
│   │   ├── circular2.test.ts
│   │   ├── custom-type.test.ts
│   │   ├── date.test.ts
│   │   ├── deprecated.test.ts
│   │   ├── enum.test.ts
│   │   ├── env.test.ts
│   │   ├── frozen.test.ts
│   │   ├── hooks.test.ts
│   │   ├── identifier.test.ts
│   │   ├── jsonpatch.test.ts
│   │   ├── late.test.ts
│   │   ├── lazy.test.ts
│   │   ├── literal.test.ts
│   │   ├── map.test.ts
│   │   ├── model.test.ts
│   │   ├── name.test.ts
│   │   ├── node.test.ts
│   │   ├── number.test.ts
│   │   ├── object-node.test.ts
│   │   ├── object.test.ts
│   │   ├── optimizations.test.ts
│   │   ├── optional-extension.test.ts
│   │   ├── optional.test.ts
│   │   ├── parent-properties.test.ts
│   │   ├── pointer.test.ts
│   │   ├── primitives.test.ts
│   │   ├── protect.test.ts
│   │   ├── recordPatches.test.ts
│   │   ├── reference-custom.test.ts
│   │   ├── reference-onInvalidated.test.ts
│   │   ├── reference.test.ts
│   │   ├── refinement.test.ts
│   │   ├── reflection.test.ts
│   │   ├── snapshotProcessor.test.ts
│   │   ├── string.test.ts
│   │   ├── this.test.ts
│   │   ├── type-system.test.ts
│   │   ├── union.test.ts
│   │   └── volatile.test.ts
│   ├── perf/
│   │   ├── fixture-data.skip.ts
│   │   ├── fixture-models.skip.ts
│   │   ├── fixtures/
│   │   │   ├── fixture-data.ts
│   │   │   └── fixture-models.ts
│   │   ├── perf.skip.ts
│   │   ├── report.ts
│   │   ├── scenarios.ts
│   │   └── timer.ts
│   ├── setup.ts
│   ├── tsconfig.json
│   └── utils.test.ts
├── bun.lockb
├── bunfig.toml
├── changelog.md
├── docker-compose.yml
├── docs/
│   ├── .gitattributes
│   ├── API/
│   │   ├── index.md
│   │   └── interfaces/
│   │       ├── customtypeoptions.md
│   │       ├── functionwithflag.md
│   │       ├── iactioncontext.md
│   │       ├── iactionrecorder.md
│   │       ├── iactiontrackingmiddleware2call.md
│   │       ├── iactiontrackingmiddleware2hooks.md
│   │       ├── iactiontrackingmiddlewarehooks.md
│   │       ├── ianycomplextype.md
│   │       ├── ianymodeltype.md
│   │       ├── ianytype.md
│   │       ├── ihooks.md
│   │       ├── ijsonpatch.md
│   │       ├── imiddlewareevent.md
│   │       ├── imodelreflectiondata.md
│   │       ├── imodelreflectionpropertiesdata.md
│   │       ├── imodeltype.md
│   │       ├── ipatchrecorder.md
│   │       ├── ireversiblejsonpatch.md
│   │       ├── iserializedactioncall.md
│   │       ├── isimpletype.md
│   │       ├── isnapshotprocessor.md
│   │       ├── isnapshotprocessors.md
│   │       ├── itype.md
│   │       ├── ivalidationcontextentry.md
│   │       ├── ivalidationerror.md
│   │       ├── referenceoptionsgetset.md
│   │       ├── referenceoptionsoninvalidated.md
│   │       └── unionoptions.md
│   ├── API_header.md
│   ├── compare/
│   │   └── context-reducer-vs-mobx-state-tree.md
│   ├── concepts/
│   │   ├── actions.md
│   │   ├── async-actions.md
│   │   ├── dependency-injection.md
│   │   ├── listeners.md
│   │   ├── middleware.md
│   │   ├── patches.md
│   │   ├── react.md
│   │   ├── reconciliation.md
│   │   ├── references.md
│   │   ├── snapshots.md
│   │   ├── trees.md
│   │   ├── views.md
│   │   └── volatiles.md
│   ├── intro/
│   │   ├── examples.md
│   │   ├── getting-started.md
│   │   ├── installation.md
│   │   ├── philosophy.md
│   │   └── welcome.md
│   ├── overview/
│   │   ├── hooks.md
│   │   ├── types.md
│   │   └── utilties.md
│   ├── recipes/
│   │   ├── auto-generated-property-setter-actions.md
│   │   ├── mst-query.md
│   │   └── pre-built-form-types-with-mst-form-type.md
│   └── tips/
│       ├── circular-deps.md
│       ├── faq.md
│       ├── inheritance.md
│       ├── more-tips.md
│       ├── resources.md
│       ├── snapshots-as-values.md
│       └── typescript.md
├── jest.config.js
├── package.json
├── rollup.config.js
├── scripts/
│   ├── fix-docs-source-links.js
│   ├── generate-compose-type.js
│   └── generate-shared.js
├── src/
│   ├── core/
│   │   ├── action.ts
│   │   ├── actionContext.ts
│   │   ├── flow.ts
│   │   ├── json-patch.ts
│   │   ├── mst-operations.ts
│   │   ├── node/
│   │   │   ├── BaseNode.ts
│   │   │   ├── Hook.ts
│   │   │   ├── create-node.ts
│   │   │   ├── identifier-cache.ts
│   │   │   ├── livelinessChecking.ts
│   │   │   ├── node-utils.ts
│   │   │   ├── object-node.ts
│   │   │   └── scalar-node.ts
│   │   ├── process.ts
│   │   └── type/
│   │       ├── type-checker.ts
│   │       └── type.ts
│   ├── index.ts
│   ├── internal.ts
│   ├── middlewares/
│   │   ├── create-action-tracking-middleware.ts
│   │   ├── createActionTrackingMiddleware2.ts
│   │   └── on-action.ts
│   ├── types/
│   │   ├── complex-types/
│   │   │   ├── array.ts
│   │   │   ├── map.ts
│   │   │   └── model.ts
│   │   ├── index.ts
│   │   ├── primitives.ts
│   │   └── utility-types/
│   │       ├── custom.ts
│   │       ├── enumeration.ts
│   │       ├── frozen.ts
│   │       ├── identifier.ts
│   │       ├── late.ts
│   │       ├── lazy.ts
│   │       ├── literal.ts
│   │       ├── maybe.ts
│   │       ├── optional.ts
│   │       ├── reference.ts
│   │       ├── refinement.ts
│   │       ├── snapshotProcessor.ts
│   │       └── union.ts
│   └── utils.ts
├── test-results/
│   └── .gitkeep
├── tsconfig.json
├── tslint.json
├── typedocconfig.js
└── website/
    ├── bun.lockb
    ├── core/
    │   └── Footer.js
    ├── i18n/
    │   └── en.json
    ├── package.json
    ├── sidebars.json
    ├── siteConfig.js
    └── static/
        ├── css/
        │   └── custom.css
        └── index.html
Download .txt
SYMBOL INDEX (1111 symbols across 85 files)

FILE: __tests__/core/1525.test.ts
  type IModel (line 16) | interface IModel extends Instance<typeof Model> {}
  type FunctionArgs (line 18) | interface FunctionArgs {

FILE: __tests__/core/2230.test.ts
  type IModelProps (line 58) | interface IModelProps extends Instance<typeof ModelProps> {}
  type IModelVolatile (line 110) | interface IModelVolatile extends Instance<typeof ModelVolatile> {}
  method vol01Var (line 113) | get vol01Var() {
  type IModelViews (line 117) | interface IModelViews extends Instance<typeof ModelViews> {}
  method getProp01 (line 120) | getProp01(): string {
  type IAction1 (line 124) | interface IAction1 extends Instance<typeof Action1> {}
  method getProp11 (line 127) | getProp11(): string {
  type IAction2 (line 131) | interface IAction2 extends Instance<typeof Action2> {}
  method getProp21 (line 134) | getProp21(): string {
  type IAction3 (line 138) | interface IAction3 extends Instance<typeof Action3> {}
  method getProp31 (line 141) | getProp31(): string {
  type IAction4 (line 145) | interface IAction4 extends Instance<typeof Action4> {}
  method getProp41 (line 148) | getProp41(): string {
  method getProp51 (line 153) | getProp51(): string {
  method getProp61 (line 158) | getProp61(): string {
  method getProp71 (line 163) | getProp71(): string {
  method getProp81 (line 168) | getProp81(): string {
  method getProp91 (line 173) | getProp91(): string {
  type IAction5 (line 177) | interface IAction5 extends Instance<typeof Action5> {}

FILE: __tests__/core/action.test.ts
  function toggle (line 24) | function toggle() {
  function setCustomer (line 113) | function setCustomer(customer: Instance<typeof Customer>) {
  function noopSetCustomer (line 116) | function noopSetCustomer(_: Instance<typeof Customer>) {
  function createTestStore (line 128) | function createTestStore() {
  function inc (line 251) | function inc() {
  function incrementBy (line 273) | function incrementBy(delta: number) {
  method inc (line 277) | inc() {
  method dec (line 280) | dec() {
  method setIncrementor (line 295) | setIncrementor(value: number) {
  method inc (line 298) | inc() {
  method a (line 323) | a(x: number) {
  method b (line 326) | b(y: number) {
  method method (line 374) | method(): number {
  method view (line 379) | view(): number {
  method remove (line 413) | remove() {
  method remove (line 422) | remove(todo: Instance<typeof Todo>) {

FILE: __tests__/core/actionTrackingMiddleware2.test.ts
  function createTestMiddleware (line 11) | function createTestMiddleware(m: any, actionName: string, value: number,...
  function doTest (line 37) | async function doTest(m: any, mode: "success" | "fail") {
  function syncTest (line 60) | async function syncTest(mode: "success" | "fail") {
  function flowTest (line 113) | async function flowTest(mode: "success" | "fail") {
  method setY (line 180) | setY() {
  method filter (line 187) | filter(call) {
  method onStart (line 193) | onStart(call) {
  method onFinish (line 198) | onFinish(call, error) {
  method test (line 248) | test() {}
  method filter (line 254) | filter(call) {
  method onStart (line 258) | onStart(call) {
  method onFinish (line 261) | onFinish(call, error) {
  method test (line 279) | async test() {}
  method filter (line 285) | filter(call) {
  method onStart (line 289) | onStart(call) {
  method onFinish (line 292) | onFinish(call, error) {
  method trackThisOne (line 312) | trackThisOne() {}
  method doNotTrackThisOne (line 313) | doNotTrackThisOne() {}
  method filter (line 319) | filter(call) {
  method onStart (line 322) | onStart(call) {
  method onFinish (line 325) | onFinish(call, error) {
  method trackThisOne (line 345) | trackThisOne() {}
  method doNotTrackThisOne (line 346) | doNotTrackThisOne() {}
  method filter (line 352) | filter(call) {
  method onStart (line 355) | onStart(call) {
  method onFinish (line 358) | onFinish(call, error) {
  method childAction1 (line 391) | childAction1() {}
  method childAction2 (line 392) | childAction2() {}
  method parentAction (line 395) | parentAction() {
  method filter (line 404) | filter(call) {
  method onStart (line 408) | onStart(call) {
  method onFinish (line 411) | onFinish(call, error) {

FILE: __tests__/core/api.test.ts
  function stringToArray (line 5) | function stringToArray(s: string): string[] {
  constant METHODS_AND_INTERNAL_TYPES (line 9) | const METHODS_AND_INTERNAL_TYPES = stringToArray(`
  constant DEPRECATED_METHODS_AND_INTERNAL_TYPES (line 89) | const DEPRECATED_METHODS_AND_INTERNAL_TYPES = stringToArray(`
  constant METHODS (line 94) | const METHODS = METHODS_AND_INTERNAL_TYPES.filter(s => s[0].toLowerCase(...
  constant INTERNAL_TYPES (line 96) | const INTERNAL_TYPES = METHODS_AND_INTERNAL_TYPES.filter(s => s[0].toUpp...
  constant TYPES (line 98) | const TYPES = stringToArray(`

FILE: __tests__/core/array.test.ts
  method setObjects (line 381) | setObjects(objects: {}[]) {
  method shift (line 466) | shift() {
  method shift (line 486) | shift() {
  method pop (line 489) | pop() {
  method clearFinishedTodos (line 542) | clearFinishedTodos() {

FILE: __tests__/core/async.test.ts
  function delay (line 19) | function delay<TV>(time: number, value: TV, shouldThrow = false): Promis...
  function testCoffeeTodo (line 28) | async function testCoffeeTodo(
  method doAction (line 282) | doAction() {
  function filterRelevantStuff (line 305) | function filterRelevantStuff(stuff: Partial<Writable<IMiddlewareEvent>>[...
  type IfAny (line 350) | type IfAny<T, Y, N> = 0 extends 1 & T ? Y : N
  function ensureNotAnyType (line 355) | function ensureNotAnyType<TExpected, TActual>(value: IfAny<TActual, neve...

FILE: __tests__/core/boxes-store.test.ts
  method width (line 21) | get width() {
  method isSelected (line 24) | get isSelected(): boolean {
  function move (line 30) | function move(dx: number, dy: number) {
  function setName (line 34) | function setName(newName: string) {
  function afterCreate (line 54) | function afterCreate() {
  function addBox (line 57) | function addBox(id: string, name: string, x: number, y: number) {
  function addArrow (line 62) | function addArrow(id: string, from: string, to: string) {
  function setSelection (line 65) | function setSelection(selection: Instance<typeof Box>) {
  function createBox (line 68) | function createBox(
  function createStore (line 88) | function createStore() {

FILE: __tests__/core/circular1.test.ts
  function LateStore1 (line 5) | function LateStore1() {
  function LateTodo1 (line 10) | function LateTodo1() {

FILE: __tests__/core/circular2.test.ts
  function LateTodo2 (line 5) | function LateTodo2() {
  function LateStore2 (line 10) | function LateStore2() {

FILE: __tests__/core/custom-type.test.ts
  class Decimal (line 12) | class Decimal {
    method constructor (line 16) | constructor(value: string) {
    method toNumber (line 22) | toNumber() {
    method toString (line 26) | toString() {
  method fromSnapshot (line 34) | fromSnapshot(value: string, env: any) {
  method toSnapshot (line 38) | toSnapshot(value: Decimal) {
  method isTargetType (line 41) | isTargetType(value: string | Decimal): value is Decimal {
  method getValidationMessage (line 44) | getValidationMessage(value: string): string {
  method fromSnapshot (line 124) | fromSnapshot(value: [number, number]) {
  method toSnapshot (line 127) | toSnapshot(value: Decimal) {
  method isTargetType (line 130) | isTargetType(value: [number, number] | Decimal): value is Decimal {
  method getValidationMessage (line 133) | getValidationMessage(value: [number, number]): string {

FILE: __tests__/core/deprecated.test.ts
  function createDeprecationListener (line 6) | function createDeprecationListener() {

FILE: __tests__/core/enum.test.ts
  type ColorEnum (line 4) | enum ColorEnum {

FILE: __tests__/core/env.test.ts
  method description (line 29) | get description() {
  function createEnvironment (line 37) | function createEnvironment() {
  function nofParents (line 156) | function nofParents(node: IAnyStateTreeNode) {
  function leafsFirst (line 166) | function leafsFirst(root: IAnyStateTreeNode) {
  function check (line 180) | function check(root: Instance<typeof RS>, name: string, mode: "detach" |...

FILE: __tests__/core/frozen.test.ts
  type Point (line 37) | type Point = { x: number; y: number }
  method moveABit (line 43) | moveABit() {

FILE: __tests__/core/hooks.test.ts
  function createTestStore (line 18) | function createTestStore(listener: (s: string) => void) {
  function listener (line 144) | function listener(e: string) {
  method afterCreate (line 153) | afterCreate() {
  method afterAttach (line 156) | afterAttach() {
  method afterCreate (line 166) | afterCreate() {
  type CarSnapshot (line 214) | type CarSnapshot = { id: string }
  function listener (line 293) | function listener(message: string) {
  function afterCreate (line 299) | function afterCreate() {
  function beforeDestroy (line 302) | function beforeDestroy() {
  function afterAttach (line 305) | function afterAttach() {
  function beforeDetach (line 308) | function beforeDetach() {
  function afterCreate (line 314) | function afterCreate() {
  function beforeDestroy (line 317) | function beforeDestroy() {
  function afterAttach (line 320) | function afterAttach() {
  function beforeDetach (line 323) | function beforeDetach() {
  function listener (line 380) | function listener(message: string) {
  method afterCreate (line 385) | afterCreate() {
  method afterAttach (line 388) | afterAttach() {
  method beforeDetach (line 391) | beforeDetach() {
  method beforeDestroy (line 394) | beforeDestroy() {
  function listener (line 421) | function listener(message: string) {
  method afterCreate (line 426) | afterCreate() {
  method afterAttach (line 429) | afterAttach() {
  method beforeDetach (line 432) | beforeDetach() {
  method beforeDestroy (line 435) | beforeDestroy() {

FILE: __tests__/core/identifier.test.ts
  method setId (line 25) | setId(id: string) {
  method addModel (line 34) | addModel(model: SnapshotOrInstance<typeof Model>) {
  function randomUuid (line 221) | function randomUuid() {
  method test1 (line 247) | test1() {
  method removeSecondItemWithDetach (line 285) | removeSecondItemWithDetach() {

FILE: __tests__/core/jsonpatch.test.ts
  function testPatches (line 20) | function testPatches<C, S, T extends object>(
  function isValid (line 355) | function isValid(str: string, array: string[], altStr?: string) {
  function isInvalid (line 379) | function isInvalid(str: string) {

FILE: __tests__/core/lazy.test.ts
  type IRootModel (line 5) | interface IRootModel {
  method area (line 16) | get area() {
  method area (line 58) | get area() {
  method rootValue (line 73) | get rootValue() {

FILE: __tests__/core/map.test.ts
  function addTodo (line 203) | function addTodo(todo: typeof Todo.Type | typeof Todo.CreationType) {
  function addTodo (line 232) | function addTodo(todo: typeof Todo.Type | typeof Todo.CreationType) {
  function addAndReturnTodo (line 265) | function addAndReturnTodo(todo: typeof Todo.Type | typeof Todo.CreationT...
  function something (line 306) | function something() {
  method remove (line 323) | remove(k: string) {
  method afterCreate (line 366) | afterCreate() {
  function addTodo (line 417) | function addTodo(aTodo: typeof Todo.Type | typeof Todo.CreationType) {

FILE: __tests__/core/model.test.ts
  method name (line 220) | get name() {
  method setName (line 240) | setName(name: string) {
  method fromSnapshot (line 282) | fromSnapshot(snapshot, _env) {
  method toSnapshot (line 285) | toSnapshot(value) {
  method isTargetType (line 288) | isTargetType(value): boolean {
  method getValidationMessage (line 291) | getValidationMessage(snapshot): string {
  method preProcessor (line 340) | preProcessor(snapshot) {
  method foo (line 498) | get foo() {

FILE: __tests__/core/node.test.ts
  function clearDone (line 295) | function clearDone() {
  function setArticle (line 336) | function setArticle(article_id: number) {
  function setCustomer (line 349) | function setCustomer(customer_id: number) {
  function addRow (line 352) | function addRow() {
  method put (line 378) | put(aUser: typeof User.CreationType | typeof User.Type) {
  method get (line 382) | get(id: string) {
  method has (line 385) | has(id: string) {
  method do (line 412) | do(fn: () => void) {

FILE: __tests__/core/object-node.test.ts
  method preProcessor (line 1264) | preProcessor(sn: any) {
  method postProcessor (line 1280) | postProcessor(sn: any, node: any) {
  method preProcessor (line 1296) | preProcessor(sn: any) {
  method postProcessor (line 1299) | postProcessor(sn: any, node: any) {

FILE: __tests__/core/object.test.ts
  function setTo (line 33) | function setTo(to: string) {
  method area (line 46) | get area() {
  method area (line 55) | get area() {
  function setWidth (line 60) | function setWidth(value: number) {
  function setHeight (line 63) | function setHeight(value: number) {
  method rename (line 87) | rename(value: string) {
  method rename (line 98) | rename(value: string) {
  method fn2 (line 290) | fn2() {}
  method fn (line 296) | fn() {
  function getError (line 328) | function getError(obj: any, path: string, subpath: string, action: strin...
  function fn (line 411) | function fn() {}
  function increment (line 469) | function increment() {
  method increment (line 477) | increment() {
  function increment (line 504) | function increment() {
  method increment (line 516) | increment() {
  method displayName (line 536) | get displayName() {
  method displayName (line 543) | get displayName() {
  method doubler (line 623) | doubler() {
  method doubler (line 642) | doubler() {
  function anotherDoubler (line 647) | function anotherDoubler() {
  method x (line 730) | get x() {
  method setX (line 735) | setX(value: number) {
  method stuff (line 755) | stuff() {}
  method toggle (line 802) | toggle() {
  method brokenView (line 809) | get brokenView() {
  method afterCreate (line 819) | afterCreate() {
  method afterAttach (line 825) | afterAttach() {
  method selectedAnswers (line 837) | get selectedAnswers() {
  method afterAttach (line 864) | afterAttach() {
  method afterAttach (line 870) | afterAttach() {
  method afterAttach (line 880) | afterAttach() {
  method afterAttach (line 891) | afterAttach() {
  method toggle (line 934) | toggle() {
  method afterCreate (line 937) | afterCreate() {
  method afterAttach (line 940) | afterAttach() {
  method afterCreate (line 946) | afterCreate() {
  method afterAttach (line 949) | afterAttach() {
  method afterCreate (line 959) | afterCreate() {
  method afterAttach (line 962) | afterAttach() {
  method afterCreate (line 973) | afterCreate() {
  method afterAttach (line 976) | afterAttach() {
  method selectedEntity (line 1155) | get selectedEntity() {
  method y (line 1190) | get y() {

FILE: __tests__/core/parent-properties.test.ts
  method parent (line 12) | get parent(): IParentModelInstance {
  method afterCreate (line 18) | afterCreate() {
  method afterAttach (line 22) | afterAttach() {
  method fetch (line 32) | get fetch() {
  type IParentModelInstance (line 37) | interface IParentModelInstance extends Instance<typeof ParentModel> {}
  method path (line 63) | get path() {
  method toggle (line 68) | toggle() {
  method path (line 81) | get path() {
  method toggle (line 86) | toggle() {
  method unfinishedTodoCount (line 96) | get unfinishedTodoCount() {
  method addTodo (line 101) | addTodo(title: string) {

FILE: __tests__/core/pointer.test.ts
  function Pointer (line 4) | function Pointer<IT extends IAnyModelType>(Model: IT) {

FILE: __tests__/core/primitives.test.ts
  function set (line 18) | function set(one: typeof Model.Type) {
  function push (line 21) | function push(model: typeof Model.Type) {

FILE: __tests__/core/protect.test.ts
  function setTitle (line 9) | function setTitle(newTitle: string) {
  function createTestStore (line 19) | function createTestStore() {
  method setParentX (line 113) | setParentX() {

FILE: __tests__/core/recordPatches.test.ts
  function testPatches (line 15) | function testPatches<C, S, T extends object>(

FILE: __tests__/core/reference-custom.test.ts
  method get (line 25) | get(identifier, parent): any {
  method set (line 32) | set(value) {
  method get (line 71) | get(identifier, parent): any {
  method set (line 76) | set(value) {
  method get (line 134) | get(identifier: string, parent): any {
  method set (line 137) | set(value) {
  method getOrLoadUser (line 160) | getOrLoadUser(name: string) {
  method get (line 194) | get(id) {
  method set (line 201) | set(value) {
  method get (line 207) | get(id) {
  method set (line 214) | set(value) {

FILE: __tests__/core/reference-onInvalidated.test.ts
  method get (line 30) | get(identifier: ReferenceIdentifier, parent: IAnyStateTreeNode | null) {
  method set (line 33) | set(value: Instance<typeof Todo>): ReferenceIdentifier {
  method deleteSqr (line 326) | deleteSqr(id: string) {

FILE: __tests__/core/reference.test.ts
  method price (line 128) | get price() {
  method price (line 164) | get price() {
  method price (line 192) | get price() {
  function addBook (line 276) | function addBook(book: SnapshotOrInstance<typeof Book>) {
  method onError (line 350) | onError(e) {
  function addFolder (line 574) | function addFolder(data: SnapshotOrInstance<typeof Folder>) {
  method putFolderHelper (line 590) | putFolderHelper(aFolder: SnapshotOrInstance<typeof Folder>) {
  function addObject (line 662) | function addObject(anItem: typeof Item.Type) {
  function addHover (line 665) | function addHover(anItem: typeof Item.Type) {
  function removeHover (line 668) | function removeHover(anItem: typeof Item.Type) {
  method order (line 775) | order() {
  method load (line 855) | load() {
  method select (line 864) | select(todo: Instance<typeof Todo>) {
  method setActiveBranch (line 932) | setActiveBranch(branchId: any) {
  method setUser (line 943) | setUser(snapshot: typeof userSnapshot) {
  method setBranchStore (line 946) | setBranchStore(snapshot: typeof branchStoreSnapshot) {
  method destroyUser (line 949) | destroyUser() {
  method destroyBranchStore (line 952) | destroyBranchStore() {
  method clearRef3 (line 1005) | clearRef3() {
  method afterCreate (line 1008) | afterCreate() {
  method dispatcher (line 1073) | dispatcher(snapshot) {

FILE: __tests__/core/reflection.test.ts
  function actionName (line 30) | function actionName() {
  method viewName (line 44) | get viewName() {
  function expectPropertyMembersToMatchMembers (line 49) | function expectPropertyMembersToMatchMembers(
  method actionName (line 160) | actionName() {
  method anotherAction (line 167) | anotherAction() {
  function flowActionName (line 173) | function flowActionName() {
  method viewName (line 187) | get viewName() {
  method anotherView (line 192) | anotherView(prop: string) {
  method actionName0 (line 219) | actionName0() {
  method actionName1 (line 226) | actionName1() {
  method actionName2 (line 232) | actionName2() {
  method view1 (line 241) | get view1() {
  method view2 (line 247) | get view2() {

FILE: __tests__/core/snapshotProcessor.test.ts
  method preProcessor (line 39) | preProcessor(sn: { x: number }) {
  method postProcessor (line 61) | postProcessor(sn, node): { x: number; val?: string } {
  method postProcessor (line 92) | postProcessor(sn, node): { x: number; val: string } {
  method preProcessor (line 115) | preProcessor(sn: { x: number }) {
  method postProcessor (line 121) | postProcessor(sn): { x: number } {
  method preProcessor (line 164) | preProcessor(sn: number) {
  method postProcessor (line 182) | postProcessor(sn, node): number {
  method preProcessor (line 203) | preProcessor(sn: number) {
  method postProcessor (line 206) | postProcessor(sn): number {
  method preProcessor (line 246) | preProcessor(sn: number[]) {
  method postProcessor (line 264) | postProcessor(sn, node): number[] {
  method preProcessor (line 286) | preProcessor(sn: number[]) {
  method postProcessor (line 289) | postProcessor(sn): number[] {
  method preProcessor (line 329) | preProcessor(sn: { x: number }) {
  method postProcessor (line 350) | postProcessor(sn, node): { x: number } {
  method preProcessor (line 375) | preProcessor(sn: { x: number }) {
  method postProcessor (line 381) | postProcessor(sn): { x: number } {
  method preProcessor (line 406) | preProcessor(sn: string) {
  method postProcessor (line 409) | postProcessor(sn): string {
  method preProcessor (line 414) | preProcessor(sn: string) {
  method postProcessor (line 417) | postProcessor(sn): string {
  method preProcessor (line 442) | preProcessor(sn: { x: string }) {
  method postProcessor (line 490) | postProcessor(sn): { x: string } {
  method preProcessor (line 538) | preProcessor(snapshot: { id: string }) {
  method addTodo (line 549) | addTodo(todo: { id: string }) {
  method setInstance (line 552) | setInstance(next: { id: string }) {
  method setInstance (line 589) | setInstance(next: { id: string }) {
  method preProcessor (line 605) | preProcessor(sn: { x: number }) {
  method preProcessor (line 625) | preProcessor(sn: { y: number }) {
  method postProcessor (line 631) | postProcessor(sn: { x: number }) {
  method preProcessor (line 675) | preProcessor(sn: { id: string; y: number }) {
  method setItems (line 685) | setItems(items: SnapshotIn<typeof SP>[]) {
  method preProcessor (line 701) | preProcessor(sn: { foo: string }) {
  method setItems (line 707) | setItems(items: SnapshotIn<typeof SP>[]) {
  method preProcessor (line 726) | preProcessor(sn: { id: string; y: number }) {
  method setItem (line 736) | setItem(item: SnapshotIn<typeof SP>) {
  method preProcessor (line 753) | preProcessor(sn: { foo: string }) {
  method setItem (line 759) | setItem(item: SnapshotIn<typeof SP>) {
  method preProcessor (line 777) | preProcessor(sn: { id: string; y: number }) {
  method setItem (line 783) | setItem(item: SnapshotIn<typeof SP>) {
  method preProcessor (line 801) | preProcessor(sn: { id: string; y: number }) {
  method setItem (line 809) | setItem(item?: SnapshotIn<typeof SP>) {
  method preProcessor (line 832) | preProcessor(sn: { id: string; y: number }) {
  method setItem (line 838) | setItem(item?: SnapshotIn<typeof SP>) {
  method setProp (line 862) | setProp(prop: typeof self.prop) {

FILE: __tests__/core/this.test.ts
  method x2 (line 10) | get x2() {
  method x4 (line 13) | get x4() {
  method boundTo (line 16) | boundTo() {
  method innerBoundTo (line 19) | innerBoundTo() {
  method isThisObservable (line 22) | isThisObservable() {
  method getLocalState (line 33) | getLocalState() {
  method getLocalState2 (line 36) | getLocalState2() {
  method xBy (line 43) | xBy(by: number) {
  method setX (line 46) | setX(x: number) {
  method setThisX (line 49) | setThisX(x: number) {
  method setXBy (line 52) | setXBy(x: number) {
  method setLocalState (line 55) | setLocalState(x: number) {

FILE: __tests__/core/type-system.test.ts
  type DifferingKeys (line 45) | type DifferingKeys<ActualT, ExpectedT> = {
  type NotExactErrorMessage (line 56) | type NotExactErrorMessage<ActualT, ExpectedT> =
  type Exact (line 65) | type Exact<A, B> = [A] extends [B] ? ([B] extends [A] ? A : never) : never
  method z (line 124) | get z(): string {
  function method (line 129) | function method() {
  function anotherMethod (line 133) | function anotherMethod(x: string) {}
  function setTitle (line 254) | function setTitle(v: string) {}
  function x (line 259) | function x(): typeof Todo.Type {
  function setTitle (line 275) | function setTitle(v: string) {}
  function setTitle (line 288) | function setTitle(v: string) {}
  function doA (line 297) | function doA() {}
  function doB (line 303) | function doB() {}
  function setTitle (line 335) | function setTitle(v: string) {}
  function getActualAmount (line 345) | function getActualAmount() {
  method amount (line 349) | get amount() {
  method getAmount (line 352) | getAmount(): number {
  function setAmount (line 358) | function setAmount() {
  function setTitle (line 374) | function setTitle(v: string) {}
  method amount (line 384) | get amount() {
  method getAmount (line 387) | getAmount(): number {
  function setAmount (line 392) | function setAmount() {
  function drive (line 423) | function drive() {}
  function afterCreate (line 424) | function afterCreate() {
  function log (line 437) | function log(msg: string) {}
  function drive (line 503) | function drive() {}
  method log (line 516) | log(msg: string) {}
  method afterCreate (line 517) | afterCreate() {
  method triple (line 531) | get triple() {
  method double (line 534) | get double() {
  type MyInterface (line 608) | interface MyInterface {
  type MyType (line 621) | type MyType = string
  method setN (line 712) | setN(nn: SnapshotOrInstance<typeof self.n>) {
  method setN2 (line 715) | setN2(nn: SnapshotOrInstance<typeof types.number>) {
  method setN3 (line 718) | setN3(nn: SnapshotOrInstance<number>) {
  method setN4 (line 721) | setN4(nn: number) {
  method setN5 (line 724) | setN5() {
  method setArr (line 729) | setArr(nn: SnapshotOrInstance<typeof self.arr>) {
  method setArr2 (line 732) | setArr2(nn: SnapshotOrInstance<typeof NumberArray>) {
  method setArr3 (line 735) | setArr3(nn: SnapshotIn<typeof NumberArray>) {
  method setArr31 (line 738) | setArr31(nn: number[]) {
  method setArr4 (line 741) | setArr4() {
  method setMap (line 748) | setMap(nn: SnapshotOrInstance<typeof self.map>) {
  method setMap2 (line 751) | setMap2(nn: SnapshotOrInstance<typeof NumberMap>) {
  method setMap3 (line 754) | setMap3(nn: SnapshotIn<typeof NumberMap>) {
  method setMap31 (line 757) | setMap31(nn: { [k: string]: number }) {
  method setMap4 (line 760) | setMap4() {
  method setA (line 771) | setA(na: SnapshotOrInstance<typeof self.a>) {
  method setA2 (line 780) | setA2(na: SnapshotOrInstance<typeof A>) {
  method setA3 (line 788) | setA3(na: SnapshotIn<typeof A>) {
  method setA4 (line 796) | setA4(na: Instance<typeof self.a>) {
  method setA5 (line 804) | setA5() {
  method do (line 883) | do() {}
  method fromSnapshot (line 976) | fromSnapshot(snapshot: C) {
  method toSnapshot (line 984) | toSnapshot(x) {
  method isTargetType (line 988) | isTargetType(v): v is T | null {
  method getValidationMessage (line 994) | getValidationMessage() {
  method toggleDone (line 1008) | toggleDone() {
  type OriginalType (line 1059) | type OriginalType = TypeOfValue<typeof t>
  method isSomePropTrue (line 1103) | get isSomePropTrue(): boolean {
  function createTypeA (line 1111) | function createTypeA<T extends ModelPropertiesDeclaration>(t: T) {
  function createTypeB (line 1119) | function createTypeB<T extends ModelPropertiesDeclaration>(t: T) {
  method root (line 1139) | get root(): IRootStore {
  method test (line 1144) | test() {
  type IRootStore (line 1151) | interface IRootStore extends Instance<typeof RootStore> {}
  type ITC (line 1178) | interface ITC extends SnapshotIn<typeof T> {}
  type ITS (line 1179) | interface ITS extends SnapshotOut<typeof T> {}
  method test (line 1206) | get test() {
  method test (line 1234) | get test() {
  type ITC (line 1266) | type ITC = SnapshotIn<typeof T>
  type ITS (line 1267) | type ITS = SnapshotOut<typeof T>
  type ITC (line 1287) | type ITC = SnapshotIn<typeof T>
  type ITS (line 1288) | type ITS = SnapshotOut<typeof T>
  method preProcessor (line 1353) | preProcessor(snapshot) {
  method postProcessor (line 1357) | postProcessor(snapshot) {
  type ITC (line 1363) | type ITC = SnapshotIn<typeof Processor>
  type ITS (line 1364) | type ITS = SnapshotOut<typeof Processor>
  method preProcessor (line 1372) | preProcessor(snapshot) {
  method postProcessor (line 1376) | postProcessor(snapshot) {
  type ITC (line 1382) | type ITC = SnapshotIn<typeof Processor>
  type ITS (line 1383) | type ITS = SnapshotOut<typeof Processor>
  method dispatcher (line 1394) | dispatcher(snapshot) {
  method dispatcher (line 1409) | dispatcher(snapshot) {

FILE: __tests__/core/union.test.ts
  method isOdd (line 143) | isOdd() {
  method isEven (line 146) | isEven() {
  method isOdd (line 151) | isOdd() {
  method isEven (line 154) | isEven() {
  function initTest (line 188) | function initTest(

FILE: __tests__/core/volatile.test.ts
  method toggle (line 13) | toggle() {
  method reload (line 16) | reload() {
  method x (line 112) | get x() {
  method setX (line 117) | setX(value: number) {
  method getX (line 147) | getX() {
  method setX (line 152) | setX(value: number) {

FILE: __tests__/perf/fixture-models.skip.ts
  constant SAMPLE_HERO (line 6) | const SAMPLE_HERO = {

FILE: __tests__/perf/fixtures/fixture-data.ts
  function createTreasure (line 8) | function createTreasure(count: number) {
  function createHeros (line 35) | function createHeros(count: number) {
  function createMonsters (line 66) | function createMonsters(count: number, treasureCount: number, heroCount:...

FILE: __tests__/perf/fixtures/fixture-models.ts
  method descriptionLength (line 20) | get descriptionLength() {
  method isAlive (line 50) | get isAlive() {
  method isFlashingRed (line 53) | get isFlashingRed() {
  method weight (line 56) | get weight() {

FILE: __tests__/perf/perf.skip.ts
  constant TOO_SLOW_MS (line 6) | const TOO_SLOW_MS = 10000

FILE: __tests__/perf/report.ts
  function leftPad (line 56) | function leftPad(value: string, length: number, char = " "): string {

FILE: __tests__/perf/scenarios.ts
  function smallScenario (line 10) | function smallScenario(count: number) {
  function mediumScenario (line 23) | function mediumScenario(count: number) {
  function largeScenario (line 38) | function largeScenario(count: number, smallChildren: number, mediumChild...

FILE: scripts/fix-docs-source-links.js
  constant DOCS_API (line 11) | const DOCS_API = path.join(__dirname, "..", "docs", "API")
  constant REPO_ROOT (line 12) | const REPO_ROOT = path.join(__dirname, "..")
  constant CANONICAL_BASE (line 13) | const CANONICAL_BASE = "https://github.com/mobxjs/mobx-state-tree/blob"
  constant LINK_REGEX (line 16) | const LINK_REGEX = /https:\/\/github\.com\/[^/]+\/mobx-state-tree\/blob\...
  function getAllMdContent (line 18) | function getAllMdContent(dir) {
  function getUniqueFilePathsFromLinks (line 32) | function getUniqueFilePathsFromLinks(content) {
  function buildFileToHashMap (line 41) | function buildFileToHashMap(filePaths) {
  function fixFile (line 57) | function fixFile(filePath, fileToHash) {
  function walk (line 69) | function walk(dir, fileToHash) {

FILE: scripts/generate-compose-type.js
  function customJoin (line 19) | function customJoin(left) {

FILE: scripts/generate-shared.js
  function getTemplateVar (line 3) | function getTemplateVar(templateVar, argNumber) {
  function getTemplateVars (line 7) | function getTemplateVars(templateVars, argNumber) {

FILE: src/core/action.ts
  type IMiddlewareEventType (line 16) | type IMiddlewareEventType =
  type IMiddlewareEvent (line 25) | interface IMiddlewareEvent extends IActionContext {
  type FunctionWithFlag (line 40) | interface FunctionWithFlag extends Function {
  type IMiddleware (line 49) | type IMiddleware = {
  type IMiddlewareHandler (line 54) | type IMiddlewareHandler = (
  function getCurrentActionContext (line 67) | function getCurrentActionContext() {
  function getNextActionId (line 75) | function getNextActionId() {
  function resetNextActionId (line 83) | function resetNextActionId() {
  function runWithActionContext (line 95) | function runWithActionContext(context: IMiddlewareEvent, fn: Function) {
  function getParentActionContext (line 120) | function getParentActionContext(parentContext: IMiddlewareEvent | undefi...
  function createActionInvoker (line 130) | function createActionInvoker<T extends FunctionWithFlag>(
  function addMiddleware (line 174) | function addMiddleware(
  function decorate (line 213) | function decorate<T extends Function>(
  class CollectedMiddlewares (line 224) | class CollectedMiddlewares {
    method constructor (line 229) | constructor(node: AnyObjectNode, fn: Function) {
    method isEmpty (line 242) | get isEmpty() {
    method getNextMiddleware (line 246) | getNextMiddleware(): IMiddleware | undefined {
  function runMiddleWares (line 259) | function runMiddleWares(

FILE: src/core/actionContext.ts
  type IActionContext (line 4) | interface IActionContext {
  function getRunningActionContext (line 26) | function getRunningActionContext(): IActionContext | undefined {
  function _isActionContextThisOrChildOf (line 34) | function _isActionContextThisOrChildOf(
  function isActionContextChildOf (line 56) | function isActionContextChildOf(
  function isActionContextThisOrChildOf (line 66) | function isActionContextThisOrChildOf(

FILE: src/core/flow.ts
  type FlowReturn (line 14) | type FlowReturn<R> = R extends Promise<infer T> ? T : R
  function flow (line 21) | function flow<R, Args extends any[]>(
  function castFlowReturn (line 34) | function castFlowReturn<T>(val: T): T {
  function toGeneratorFunction (line 60) | function toGeneratorFunction<R, Args extends any[]>(p: (...args: Args) =...
  function createFlowSpawner (line 95) | function createFlowSpawner(name: string, generator: FunctionWithFlag) {

FILE: src/core/json-patch.ts
  type IJsonPatch (line 7) | interface IJsonPatch {
  type IReversibleJsonPatch (line 13) | interface IReversibleJsonPatch extends IJsonPatch {
  function splitPatch (line 21) | function splitPatch(patch: IReversibleJsonPatch): [IJsonPatch, IJsonPatc...
  function stripPatch (line 31) | function stripPatch(patch: IReversibleJsonPatch): IJsonPatch {
  function invertPatch (line 44) | function invertPatch(patch: IReversibleJsonPatch): IJsonPatch {
  function isNumber (line 69) | function isNumber(x: string): boolean {
  function escapeJsonPath (line 78) | function escapeJsonPath(path: string): string {
  function unescapeJsonPath (line 89) | function unescapeJsonPath(path: string): string {
  function joinJsonPath (line 99) | function joinJsonPath(path: string[]): string {
  function splitJsonPath (line 119) | function splitJsonPath(path: string): string[] {

FILE: src/core/mst-operations.ts
  type TypeOrStateTreeNodeToStateTreeNode (line 37) | type TypeOrStateTreeNodeToStateTreeNode<T extends IAnyType | IAnyStateTr...
  function getType (line 46) | function getType(object: IAnyStateTreeNode): IAnyComplexType {
  function getChildType (line 68) | function getChildType(object: IAnyStateTreeNode, propertyName?: string):...
  function onPatch (line 83) | function onPatch(
  function onSnapshot (line 103) | function onSnapshot<S>(
  function applyPatch (line 124) | function applyPatch(
  type IPatchRecorder (line 135) | interface IPatchRecorder {
  function recordPatches (line 177) | function recordPatches(
  function protect (line 265) | function protect(target: IAnyStateTreeNode): void {
  function unprotect (line 298) | function unprotect(target: IAnyStateTreeNode): void {
  function isProtected (line 310) | function isProtected(target: IAnyStateTreeNode): boolean {
  function applySnapshot (line 321) | function applySnapshot<C>(target: IStateTreeNode<IType<C, any, any>>, sn...
  function getSnapshot (line 336) | function getSnapshot<S>(
  function hasParent (line 356) | function hasParent(target: IAnyStateTreeNode, depth: number = 1): boolean {
  function getParent (line 382) | function getParent<IT extends IAnyStateTreeNode | IAnyComplexType>(
  function hasParentOfType (line 406) | function hasParentOfType(target: IAnyStateTreeNode, type: IAnyComplexTyp...
  function getParentOfType (line 426) | function getParentOfType<IT extends IAnyComplexType>(
  function getRoot (line 451) | function getRoot<IT extends IAnyComplexType | IAnyStateTreeNode>(
  function getPath (line 466) | function getPath(target: IAnyStateTreeNode): string {
  function getPathParts (line 479) | function getPathParts(target: IAnyStateTreeNode): string[] {
  function isRoot (line 492) | function isRoot(target: IAnyStateTreeNode): boolean {
  function resolvePath (line 507) | function resolvePath(target: IAnyStateTreeNode, path: string): any {
  function resolveIdentifier (line 525) | function resolveIdentifier<IT extends IAnyModelType>(
  function getIdentifier (line 549) | function getIdentifier(target: IAnyStateTreeNode): string | null {
  function tryReference (line 564) | function tryReference<N extends IAnyStateTreeNode>(
  function isValidReference (line 596) | function isValidReference<N extends IAnyStateTreeNode>(
  function tryResolve (line 624) | function tryResolve(target: IAnyStateTreeNode, path: string): any {
  function getRelativePath (line 648) | function getRelativePath(base: IAnyStateTreeNode, target: IAnyStateTreeN...
  function clone (line 666) | function clone<T extends IAnyStateTreeNode>(
  function detach (line 687) | function detach<T extends IAnyStateTreeNode>(target: T): T {
  function destroy (line 698) | function destroy(target: IAnyStateTreeNode): void {
  function isAlive (line 716) | function isAlive(target: IAnyStateTreeNode): boolean {
  function addDisposer (line 751) | function addDisposer(target: IAnyStateTreeNode, disposer: IDisposer): ID...
  function getEnv (line 773) | function getEnv<T = any>(target: IAnyStateTreeNode): T {
  function hasEnv (line 790) | function hasEnv(target: IAnyStateTreeNode): boolean {
  function walk (line 808) | function walk(
  type IModelReflectionPropertiesData (line 824) | interface IModelReflectionPropertiesData {
  function getPropertyMembers (line 835) | function getPropertyMembers(
  type IModelReflectionData (line 854) | interface IModelReflectionData extends IModelReflectionPropertiesData {
  function getMembers (line 874) | function getMembers(target: IAnyStateTreeNode): IModelReflectionData {
  function cast (line 946) | function cast(snapshotOrInstance: any): any {
  function castToSnapshot (line 977) | function castToSnapshot<I>(
  function castToReferenceSnapshot (line 1011) | function castToReferenceSnapshot<I>(
  function getNodeId (line 1026) | function getNodeId(target: IAnyStateTreeNode): number {

FILE: src/core/node/BaseNode.ts
  type HookSubscribers (line 14) | type HookSubscribers = {
  method subpath (line 30) | get subpath() {
  method subpathUponDeath (line 35) | get subpathUponDeath() {
  method pathUponDeath (line 40) | protected get pathUponDeath() {
  method value (line 45) | get value(): T {
  method state (line 51) | get state() {
  method state (line 54) | set state(val: NodeLifeCycle) {
  method fireInternalHook (line 68) | protected fireInternalHook(name: Hook) {
  method registerHook (line 74) | registerHook<H extends Hook>(hook: H, hookHandler: HookSubscribers[H]): ...
  method parent (line 82) | get parent() {
  method constructor (line 86) | constructor(
  method getReconciliationType (line 96) | getReconciliationType() {
  method baseSetParent (line 101) | protected baseSetParent(parent: AnyObjectNode | null, subpath: string) {
  method path (line 113) | get path(): string {
  method getEscapedPath (line 117) | protected getEscapedPath(reportObserved: boolean): string {
  method isRoot (line 132) | get isRoot(): boolean {
  method isAlive (line 143) | get isAlive() {
  method isDetaching (line 147) | get isDetaching() {
  method observableIsAlive (line 151) | get observableIsAlive() {
  method baseFinalizeCreation (line 163) | protected baseFinalizeCreation(whenFinalized?: () => void) {
  method baseFinalizeDeath (line 193) | protected baseFinalizeDeath() {
  method baseAboutToDie (line 206) | protected baseAboutToDie() {
  type AnyNode (line 215) | type AnyNode = BaseNode<any, any, any>

FILE: src/core/node/Hook.ts
  type Hook (line 4) | enum Hook {
  type IHooks (line 12) | interface IHooks {
  type IHooksGetter (line 19) | type IHooksGetter<T> = (self: T) => IHooks

FILE: src/core/node/create-node.ts
  function createObjectNode (line 16) | function createObjectNode<C, S, T>(
  function createScalarNode (line 50) | function createScalarNode<C, S, T>(
  function isNode (line 64) | function isNode(value: any): value is AnyNode {

FILE: src/core/node/identifier-cache.ts
  class IdentifierCache (line 10) | class IdentifierCache {
    method constructor (line 20) | constructor() {}
    method updateLastCacheModificationPerId (line 22) | private updateLastCacheModificationPerId(identifier: string) {
    method getLastCacheModificationPerId (line 28) | getLastCacheModificationPerId(identifier: string): string {
    method addNodeToCache (line 33) | addNodeToCache(node: AnyObjectNode, lastCacheUpdate = true): void {
    method mergeCache (line 48) | mergeCache(node: AnyObjectNode) {
    method notifyDied (line 56) | notifyDied(node: AnyObjectNode) {
    method splitCache (line 71) | splitCache(splitNode: AnyObjectNode): IdentifierCache {
    method has (line 98) | has(type: IAnyComplexType, identifier: string): boolean {
    method resolve (line 104) | resolve<IT extends IAnyComplexType>(

FILE: src/core/node/livelinessChecking.ts
  type LivelinessMode (line 7) | type LivelinessMode = "warn" | "error" | "ignore"
  function setLivelinessChecking (line 18) | function setLivelinessChecking(mode: LivelinessMode) {
  function getLivelinessChecking (line 27) | function getLivelinessChecking(): LivelinessMode {
  type LivelynessMode (line 35) | type LivelynessMode = LivelinessMode
  function setLivelynessChecking (line 47) | function setLivelynessChecking(mode: LivelinessMode) {

FILE: src/core/node/node-utils.ts
  type NodeLifeCycle (line 23) | enum NodeLifeCycle {
  type IStateTreeNode (line 38) | interface IStateTreeNode<IT extends IAnyType = IAnyType> {
  type TypeOfValue (line 50) | type TypeOfValue<T extends IAnyStateTreeNode> =
  type IAnyStateTreeNode (line 57) | interface IAnyStateTreeNode extends STNValue<any, IAnyType> {}
  function isStateTreeNode (line 67) | function isStateTreeNode<IT extends IAnyComplexType = IAnyComplexType>(
  function assertIsStateTreeNode (line 77) | function assertIsStateTreeNode(
  function getStateTreeNode (line 88) | function getStateTreeNode(value: IAnyStateTreeNode): AnyObjectNode {
  function getStateTreeNodeSafe (line 100) | function getStateTreeNodeSafe(value: IAnyStateTreeNode): AnyObjectNode |...
  function toJSON (line 108) | function toJSON<S>(this: IStateTreeNode<IType<any, S, any>>): S {
  function getRelativePathBetweenNodes (line 118) | function getRelativePathBetweenNodes(base: AnyObjectNode, target: AnyObj...
  function resolveNodeByPath (line 142) | function resolveNodeByPath(
  function resolveNodeByPathParts (line 154) | function resolveNodeByPathParts(
  function convertChildNodesToArray (line 205) | function convertChildNodesToArray(childNodes: IChildNodesMap | null): An...

FILE: src/core/node/object-node.ts
  type ObservableInstanceLifecycle (line 44) | const enum ObservableInstanceLifecycle {
  type InternalEvents (line 53) | const enum InternalEvents {
  type IChildNodesMap (line 63) | interface IChildNodesMap {
  method onError (line 68) | onError(e: any) {
  type InternalEventHandlers (line 73) | type InternalEventHandlers<S> = {
  class ObjectNode (line 83) | class ObjectNode<C, S, T> extends BaseNode<C, S, T> {
    method applyPatches (line 99) | applyPatches(patches: IJsonPatch[]): void {
    method applySnapshot (line 106) | applySnapshot(snapshot: C): void {
    method constructor (line 122) | constructor(
    method createObservableInstanceIfNeeded (line 175) | createObservableInstanceIfNeeded(fireHooks = true): void {
    method createObservableInstance (line 181) | createObservableInstance(fireHooks = true): void {
    method root (line 259) | get root(): AnyObjectNode {
    method clearParent (line 264) | clearParent(): void {
    method setParent (line 286) | setParent(newParent: AnyObjectNode, subpath: string): void {
    method fireHook (line 337) | protected fireHook(name: Hook): void {
    method snapshot (line 359) | get snapshot(): S {
    method getSnapshot (line 367) | getSnapshot(): S {
    method _getActualSnapshot (line 374) | private _getActualSnapshot(): S {
    method _getCachedInitialSnapshot (line 378) | private _getCachedInitialSnapshot(): S {
    method isRunningAction (line 391) | private isRunningAction(): boolean {
    method assertAlive (line 397) | assertAlive(context: AssertAliveContext): void {
    method _getAssertAliveError (line 410) | private _getAssertAliveError(context: AssertAliveContext): string {
    method getChildNode (line 433) | getChildNode(subpath: string): AnyNode {
    method getChildren (line 447) | getChildren(): ReadonlyArray<AnyNode> {
    method getChildType (line 459) | getChildType(propertyName?: string): IAnyType {
    method isProtected (line 463) | get isProtected(): boolean {
    method assertWritable (line 467) | assertWritable(context: AssertAliveContext): void {
    method removeChild (line 476) | removeChild(subpath: string): void {
    method unbox (line 481) | unbox(childNode: AnyNode | undefined): AnyNode | undefined {
    method toString (line 490) | toString(): string {
    method finalizeCreation (line 496) | finalizeCreation(): void {
    method detach (line 506) | detach(): void {
    method preboot (line 512) | private preboot(): void {
    method die (line 544) | die(): void {
    method aboutToDie (line 550) | aboutToDie(): void {
    method finalizeDeath (line 567) | finalizeDeath(): void {
    method onSnapshot (line 583) | onSnapshot(onChange: (snapshot: S) => void): IDisposer {
    method emitSnapshot (line 588) | protected emitSnapshot(snapshot: S): void {
    method onPatch (line 592) | onPatch(handler: (patch: IJsonPatch, reversePatch: IJsonPatch) => void...
    method emitPatch (line 596) | emitPatch(basePatch: IReversibleJsonPatch, source: AnyNode): void {
    method hasDisposer (line 608) | hasDisposer(disposer: () => void): boolean {
    method addDisposer (line 612) | addDisposer(disposer: () => void): void {
    method removeDisposer (line 620) | removeDisposer(disposer: () => void): void {
    method removeMiddleware (line 627) | private removeMiddleware(middleware: IMiddleware): void {
    method addMiddleWare (line 636) | addMiddleWare(handler: IMiddlewareHandler, includeHooks: boolean = tru...
    method applyPatchLocally (line 646) | applyPatchLocally(subpath: string, patch: IJsonPatch): void {
    method _addSnapshotReaction (line 654) | private _addSnapshotReaction(): void {
    method _internalEventsHasSubscribers (line 672) | private _internalEventsHasSubscribers(event: InternalEvents): boolean {
    method _internalEventsRegister (line 676) | private _internalEventsRegister<IE extends InternalEvents>(
    method _internalEventsHas (line 687) | private _internalEventsHas<IE extends InternalEvents>(
    method _internalEventsUnregister (line 694) | private _internalEventsUnregister<IE extends InternalEvents>(
    method _internalEventsEmit (line 703) | private _internalEventsEmit<IE extends InternalEvents>(
    method _internalEventsClear (line 712) | private _internalEventsClear(event: InternalEvents): void {
    method _internalEventsClearAll (line 718) | private _internalEventsClearAll(): void {
  type AnyObjectNode (line 736) | type AnyObjectNode = ObjectNode<any, any, any>
  type AssertAliveContext (line 742) | interface AssertAliveContext {

FILE: src/core/node/scalar-node.ts
  class ScalarNode (line 17) | class ScalarNode<C, S, T> extends BaseNode<C, S, T> {
    method constructor (line 26) | constructor(
    method root (line 50) | get root(): AnyObjectNode {
    method setParent (line 56) | setParent(newParent: AnyObjectNode, subpath: string): void {
    method snapshot (line 83) | get snapshot(): S {
    method getSnapshot (line 87) | getSnapshot(): S {
    method toString (line 91) | toString(): string {
    method die (line 96) | die(): void {
    method finalizeCreation (line 102) | finalizeCreation(): void {
    method aboutToDie (line 106) | aboutToDie(): void {
    method finalizeDeath (line 110) | finalizeDeath(): void {
    method fireHook (line 114) | protected fireHook(name: Hook): void {

FILE: src/core/process.ts
  constant DEPRECATION_MESSAGE (line 13) | const DEPRECATION_MESSAGE =
  function process (line 94) | function process(asyncAction: any): any {
  function createProcessSpawner (line 103) | function createProcessSpawner(name: string, generator: Function) {

FILE: src/core/type/type-checker.ts
  type IValidationContextEntry (line 15) | interface IValidationContextEntry {
  type IValidationContext (line 23) | type IValidationContext = IValidationContextEntry[]
  type IValidationError (line 26) | interface IValidationError {
  type IValidationResult (line 36) | type IValidationResult = IValidationError[]
  function safeStringify (line 38) | function safeStringify(value: any) {
  function prettyPrintValue (line 51) | function prettyPrintValue(value: any) {
  function shortenPrintValue (line 59) | function shortenPrintValue(valueInString: string) {
  function toErrorString (line 65) | function toErrorString(error: IValidationError): string {
  function getContextForPath (line 105) | function getContextForPath(
  function typeCheckSuccess (line 117) | function typeCheckSuccess(): IValidationResult {
  function typeCheckFailure (line 125) | function typeCheckFailure(
  function flattenTypeErrors (line 137) | function flattenTypeErrors(errors: IValidationResult[]): IValidationResu...
  function typecheckInternal (line 146) | function typecheckInternal<IT extends IAnyType>(
  function typecheck (line 164) | function typecheck<IT extends IAnyType>(type: IT, value: ExtractCSTWithS...
  function validationErrorsToString (line 172) | function validationErrorsToString<IT extends IAnyType>(

FILE: src/core/type/type.ts
  type TypeFlags (line 33) | enum TypeFlags {
  type STNValue (line 70) | type STNValue<T, IT extends IAnyType> = T extends object ? T & IStateTre...
  type ExcludeReadonly (line 75) | type ExcludeReadonly<T> = T extends {} ? T[WritableKeys<T>] : T
  type IType (line 80) | interface IType<C, S, T> {
  type IAnyType (line 200) | interface IAnyType extends IType<any, any, any> {}
  type ISimpleType (line 205) | interface ISimpleType<T> extends IType<T, T, T> {}
  type Primitives (line 208) | type Primitives = ModelPrimitive | null | undefined
  type IComplexType (line 215) | interface IComplexType<C, S, T> extends IType<C, S, T & object> {}
  type IAnyComplexType (line 220) | interface IAnyComplexType extends IType<any, any, object> {}
  type ExtractCSTWithoutSTN (line 223) | type ExtractCSTWithoutSTN<
  type ExtractCSTWithSTN (line 227) | type ExtractCSTWithSTN<
  type Instance (line 234) | type Instance<T> = T extends { [$type]: undefined; Type: any } ? T["Type...
  type SnapshotIn (line 239) | type SnapshotIn<T> = T extends { [$type]: undefined; CreationType: any }
  type SnapshotOut (line 248) | type SnapshotOut<T> = T extends { [$type]: undefined; SnapshotType: any }
  type SnapshotOrInstance (line 280) | type SnapshotOrInstance<T> = SnapshotIn<T> | Instance<T>
  method constructor (line 302) | constructor(name: string) {
  method create (line 306) | create(snapshot?: C, environment?: any) {
  method getSnapshot (line 311) | getSnapshot(node: N, applyPostProcess?: boolean): S {
  method isAssignableFrom (line 330) | isAssignableFrom(type: IAnyType): boolean {
  method validate (line 334) | validate(value: C | T, context: IValidationContext): IValidationResult {
  method is (line 346) | is(thing: any): thing is any {
  method Type (line 350) | get Type(): any {
  method TypeWithoutSTN (line 356) | get TypeWithoutSTN(): any {
  method SnapshotType (line 362) | get SnapshotType(): any {
  method CreationType (line 368) | get CreationType(): any {
  type AnyBaseType (line 383) | type AnyBaseType = BaseType<any, any, any, any>
  type ExtractNodeType (line 389) | type ExtractNodeType<IT extends IAnyType> =
  method constructor (line 401) | constructor(name: string) {
  method create (line 405) | create(snapshot: C = this.getDefaultSnapshot(), environment?: any) {
  method getValue (line 409) | getValue(node: this["N"]): T {
  method isMatchingSnapshotId (line 429) | isMatchingSnapshotId(current: this["N"], snapshot: C): boolean {
  method tryToReconcileNode (line 437) | private tryToReconcileNode(current: this["N"], newValue: C | T) {
  method reconcile (line 461) | reconcile(
  method getSubTypes (line 486) | getSubTypes() {
  method createNewInstance (line 504) | createNewInstance(snapshot: C): T {
  method getValue (line 508) | getValue(node: this["N"]): T {
  method getSnapshot (line 517) | getSnapshot(node: this["N"]): S {
  method reconcile (line 521) | reconcile(current: this["N"], newValue: C, parent: AnyObjectNode, subpat...
  method getSubTypes (line 531) | getSubTypes() {
  function isType (line 542) | function isType(value: any): value is IAnyType {
  function assertIsType (line 550) | function assertIsType(type: IAnyType, argNumber: number | number[]) {

FILE: src/middlewares/create-action-tracking-middleware.ts
  type IActionTrackingMiddlewareHooks (line 5) | interface IActionTrackingMiddlewareHooks<T> {
  function createActionTrackingMiddleware (line 28) | function createActionTrackingMiddleware<T = any>(

FILE: src/middlewares/createActionTrackingMiddleware2.ts
  type IActionTrackingMiddleware2Call (line 3) | interface IActionTrackingMiddleware2Call<TEnv> extends Readonly<IActionC...
  type IActionTrackingMiddleware2Hooks (line 8) | interface IActionTrackingMiddleware2Hooks<TEnv> {
  class RunningAction (line 14) | class RunningAction {
    method constructor (line 18) | constructor(
    method finish (line 27) | finish(error?: any) {
    method incFlowsPending (line 36) | incFlowsPending() {
    method decFlowsPending (line 40) | decFlowsPending() {
    method hasFlowsPending (line 44) | get hasFlowsPending() {
  function createActionTrackingMiddleware2 (line 72) | function createActionTrackingMiddleware2<TEnv = any>(

FILE: src/middlewares/on-action.ts
  type ISerializedActionCall (line 30) | interface ISerializedActionCall {
  type IActionRecorder (line 36) | interface IActionRecorder {
  function serializeArgument (line 44) | function serializeArgument(node: AnyNode, actionName: string, index: num...
  function deserializeArgument (line 68) | function deserializeArgument(adm: AnyNode, value: any): any {
  function serializeTheUnserializable (line 74) | function serializeTheUnserializable(baseType: string) {
  function applyAction (line 89) | function applyAction(
  function baseApplyAction (line 102) | function baseApplyAction(target: IAnyStateTreeNode, action: ISerializedA...
  function recordActions (line 148) | function recordActions(
  function onAction (line 226) | function onAction(

FILE: src/types/complex-types/array.ts
  type IMSTArray (line 52) | interface IMSTArray<IT extends IAnyType> extends IObservableArray<IT["Ty...
  type IArrayType (line 72) | interface IArrayType<IT extends IAnyType>
  class ArrayType (line 81) | class ArrayType<IT extends IAnyType> extends ComplexType<
    method constructor (line 88) | constructor(
    method hooks (line 97) | hooks(hooks: IHooksGetter<IMSTArray<IT>>) {
    method instantiate (line 103) | instantiate(
    method initializeChildNodes (line 112) | initializeChildNodes(objNode: this["N"], snapshot: this["C"] = []): IC...
    method createNewInstance (line 122) | createNewInstance(childNodes: IChildNodesMap): this["T"] {
    method finalizeNewInstance (line 127) | finalizeNewInstance(node: this["N"], instance: this["T"]): void {
    method describe (line 148) | describe() {
    method getChildren (line 152) | getChildren(node: this["N"]): AnyNode[] {
    method getChildNode (line 156) | getChildNode(node: this["N"], key: string): AnyNode {
    method willChange (line 162) | willChange(
    method getSnapshot (line 214) | getSnapshot(node: this["N"]): this["S"] {
    method processInitialSnapshot (line 218) | processInitialSnapshot(childNodes: IChildNodesMap): this["S"] {
    method didChange (line 226) | didChange(change: IArrayDidChange<AnyNode>): void {
    method applyPatchLocally (line 276) | applyPatchLocally(node: this["N"], subpath: string, patch: IJsonPatch)...
    method applySnapshot (line 292) | applySnapshot(node: this["N"], snapshot: this["C"]): void {
    method getChildType (line 298) | getChildType(): IAnyType {
    method isValidSnapshot (line 302) | isValidSnapshot(value: this["C"], context: IValidationContext): IValid...
    method getDefaultSnapshot (line 314) | getDefaultSnapshot(): this["C"] {
    method removeChild (line 318) | removeChild(node: this["N"], subpath: string) {
  function array (line 348) | function array<IT extends IAnyType>(subtype: IT): IArrayType<IT> {
  function reconcileArrayChildren (line 353) | function reconcileArrayChildren<TT>(
  function valueAsNode (line 427) | function valueAsNode(
  function areSame (line 473) | function areSame(oldNode: AnyNode, newValue: any) {
  function isArrayType (line 512) | function isArrayType(type: unknown): type is IArrayType<IAnyType> {

FILE: src/types/complex-types/map.ts
  type IMapType (line 58) | interface IMapType<IT extends IAnyType>
  type IMSTMap (line 68) | interface IMSTMap<IT extends IAnyType> {
  function tryCollectModelTypes (line 119) | function tryCollectModelTypes(type: IAnyType, modelTypes: Array<IAnyMode...
  type MapIdentifierMode (line 140) | enum MapIdentifierMode {
  class MSTMap (line 146) | class MSTMap<IT extends IAnyType> extends ObservableMap<string, any> {
    method constructor (line 147) | constructor(initialData?: IObservableMapInitialValues<string, any> | u...
    method get (line 151) | get(key: string): IT["Type"] | undefined {
    method has (line 156) | has(key: string) {
    method delete (line 160) | delete(key: string) {
    method set (line 164) | set(key: string, value: ExtractCSTWithSTN<IT>): this {
    method put (line 168) | put(value: ExtractCSTWithSTN<IT>): IT["Type"] {
  class MapType (line 211) | class MapType<IT extends IAnyType> extends ComplexType<
    method constructor (line 222) | constructor(
    method hooks (line 232) | hooks(hooks: IHooksGetter<IMSTMap<IT>>) {
    method instantiate (line 238) | instantiate(
    method _determineIdentifierMode (line 248) | private _determineIdentifierMode() {
    method initializeChildNodes (line 277) | initializeChildNodes(objNode: this["N"], initialSnapshot: this["C"] = ...
    method createNewInstance (line 287) | createNewInstance(childNodes: IChildNodesMap): this["T"] {
    method finalizeNewInstance (line 291) | finalizeNewInstance(node: this["N"], instance: ObservableMap<string, a...
    method describe (line 312) | describe() {
    method getChildren (line 316) | getChildren(node: this["N"]): ReadonlyArray<AnyNode> {
    method getChildNode (line 321) | getChildNode(node: this["N"], key: string): AnyNode {
    method willChange (line 327) | willChange(change: IMapWillChange<string, AnyNode>): IMapWillChange<st...
    method processIdentifier (line 361) | private processIdentifier(expected: string, node: AnyNode): void {
    method getSnapshot (line 371) | getSnapshot(node: this["N"]): this["S"] {
    method processInitialSnapshot (line 379) | processInitialSnapshot(childNodes: IChildNodesMap): this["S"] {
    method didChange (line 387) | didChange(change: IMapDidChange<string, AnyNode>): void {
    method applyPatchLocally (line 426) | applyPatchLocally(node: this["N"], subpath: string, patch: IJsonPatch)...
    method applySnapshot (line 439) | applySnapshot(node: this["N"], snapshot: this["C"]): void {
    method getChildType (line 458) | getChildType(): IAnyType {
    method isValidSnapshot (line 462) | isValidSnapshot(value: this["C"], context: IValidationContext): IValid...
    method getDefaultSnapshot (line 474) | getDefaultSnapshot(): this["C"] {
    method removeChild (line 478) | removeChild(node: this["N"], subpath: string) {
  function map (line 511) | function map<IT extends IAnyType>(subtype: IT): IMapType<IT> {
  function isMapType (line 521) | function isMapType(type: unknown): type is IMapType<IAnyType> {

FILE: src/types/complex-types/model.ts
  constant PRE_PROCESS_SNAPSHOT (line 60) | const PRE_PROCESS_SNAPSHOT = "preProcessSnapshot"
  constant POST_PROCESS_SNAPSHOT (line 61) | const POST_PROCESS_SNAPSHOT = "postProcessSnapshot"
  type ModelProperties (line 64) | interface ModelProperties {
  type ModelPrimitive (line 69) | type ModelPrimitive = string | number | boolean | Date | bigint
  type ModelPropertiesDeclaration (line 72) | interface ModelPropertiesDeclaration {
  type ModelPropertiesDeclarationToProperties (line 81) | type ModelPropertiesDeclarationToProperties<T extends ModelPropertiesDec...
  type IsOptionalValue (line 110) | type IsOptionalValue<C, TV, FV> = undefined extends C ? TV : FV
  type AnyObject (line 119) | type AnyObject = Record<string, any>
  type DefinablePropsNames (line 125) | type DefinablePropsNames<T> = { [K in keyof T]: IsOptionalValue<T[K], ne...
  type ExtractCFromProps (line 128) | type ExtractCFromProps<P extends ModelProperties> = MaybeEmpty<{
  type MaybeEmpty (line 133) | type MaybeEmpty<T> = keyof T extends never ? EmptyObject : T
  type ModelCreationType (line 136) | type ModelCreationType<PC> = MaybeEmpty<{ [P in DefinablePropsNames<PC>]...
  type WithAdditionalProperties (line 143) | type WithAdditionalProperties<T> = T extends Record<string, never> ? Emp...
  type EmptyObject (line 146) | type EmptyObject = { [$nonEmptyObject]?: never }
  type ModelCreationType2 (line 149) | type ModelCreationType2<P extends ModelProperties, CustomC> = MaybeEmpty<
  type ModelSnapshotType (line 156) | type ModelSnapshotType<P extends ModelProperties> = {
  type ModelSnapshotType2 (line 161) | type ModelSnapshotType2<P extends ModelProperties, CustomS> = _CustomOrO...
  type ModelInstanceTypeProps (line 170) | type ModelInstanceTypeProps<P extends ModelProperties> = {
  type ModelInstanceType (line 178) | type ModelInstanceType<P extends ModelProperties, O> = ModelInstanceType...
  type ModelActions (line 181) | interface ModelActions {
  type IModelType (line 185) | interface IModelType<
  type IAnyModelType (line 233) | interface IAnyModelType extends IModelType<any, any, any, any> {}
  type ExtractProps (line 236) | type ExtractProps<T extends IAnyModelType> =
  type ExtractOthers (line 240) | type ExtractOthers<T extends IAnyModelType> =
  function objectTypeToString (line 243) | function objectTypeToString(this: any) {
  type ModelTypeConfig (line 251) | interface ModelTypeConfig {
  function toPropertiesObject (line 265) | function toPropertiesObject(declaredProps: ModelPropertiesDeclaration): ...
  class ModelType (line 343) | class ModelType<
    method constructor (line 369) | constructor(opts: ModelTypeConfig) {
    method _getIdentifierAttribute (line 379) | private _getIdentifierAttribute(): string | undefined {
    method cloneAndEnhance (line 393) | cloneAndEnhance(opts: ModelTypeConfig): IAnyModelType {
    method actions (line 403) | actions<A extends ModelActions>(fn: (self: Instance<this>) => A) {
    method instantiateActions (line 411) | private instantiateActions(self: this["T"], actions: ModelActions): vo...
    method volatile (line 470) | volatile<TP extends object>(fn: (self: Instance<this>) => TP) {
    method instantiateVolatileState (line 483) | private instantiateVolatileState(
    method extend (line 507) | extend<A extends ModelActions = {}, V extends Object = {}, VS extends ...
    method views (line 524) | views<V extends Object>(fn: (self: Instance<this>) => V) {
    method instantiateViews (line 532) | private instantiateViews(self: this["T"], views: Object): void {
    method instantiate (line 582) | instantiate(
    method initializeChildNodes (line 596) | initializeChildNodes(objNode: this["N"], initialSnapshot: any = {}): I...
    method createNewInstance (line 610) | createNewInstance(childNodes: IChildNodesMap): this["T"] {
    method finalizeNewInstance (line 615) | finalizeNewInstance(node: this["N"], instance: this["T"]): void {
    method willChange (line 627) | private willChange(chg: IObjectWillChange): IObjectWillChange | null {
    method didChange (line 648) | private didChange(chg: IObjectDidChange) {
    method getChildren (line 670) | getChildren(node: this["N"]): ReadonlyArray<AnyNode> {
    method getChildNode (line 678) | getChildNode(node: this["N"], key: string): AnyNode {
    method getSnapshot (line 686) | getSnapshot(node: this["N"], applyPostProcess = true): this["S"] {
    method processInitialSnapshot (line 701) | processInitialSnapshot(childNodes: IChildNodesMap): this["S"] {
    method applyPatchLocally (line 709) | applyPatchLocally(node: this["N"], subpath: string, patch: IJsonPatch)...
    method applySnapshot (line 716) | applySnapshot(node: this["N"], snapshot: this["C"]): void {
    method applySnapshotPreProcessor (line 724) | applySnapshotPreProcessor(snapshot: any) {
    method applySnapshotPostProcessor (line 729) | applySnapshotPostProcessor(snapshot: any) {
    method getChildType (line 735) | getChildType(propertyName: string): IAnyType {
    method isValidSnapshot (line 741) | isValidSnapshot(value: this["C"], context: IValidationContext): IValid...
    method forAllProps (line 758) | private forAllProps(fn: (name: string, type: IAnyType) => void) {
    method describe (line 762) | describe() {
    method getDefaultSnapshot (line 771) | getDefaultSnapshot(): this["C"] {
    method removeChild (line 775) | removeChild(node: this["N"], subpath: string) {
  function model (line 793) | function model(...args: any[]): any {
  type _CustomJoin (line 808) | type _CustomJoin<A, B> = A extends _NotCustomized ? B : A & B
  function compose (line 861) | function compose(...args: any[]): any {
  function isModelType (line 897) | function isModelType(type: unknown): type is IAnyModelType {

FILE: src/types/primitives.ts
  class CoreType (line 27) | class CoreType<C, S, T> extends SimpleType<C, S, T> {
    method constructor (line 28) | constructor(
    method describe (line 38) | describe() {
    method instantiate (line 42) | instantiate(
    method createNewInstance (line 51) | createNewInstance(snapshot: C) {
    method isValidSnapshot (line 55) | isValidSnapshot(value: C, context: IValidationContext): IValidationRes...
  function getPrimitiveFactoryFromValue (line 259) | function getPrimitiveFactoryFromValue(value: any): ISimpleType<any> {
  function isPrimitiveType (line 281) | function isPrimitiveType(

FILE: src/types/utility-types/custom.ts
  type CustomTypeOptions (line 13) | interface CustomTypeOptions<S, T> {
  function custom (line 74) | function custom<S, T>(options: CustomTypeOptions<S, T>): IType<S | T, S,...
  class CustomType (line 82) | class CustomType<S, T> extends SimpleType<S | T, S, T> {
    method constructor (line 85) | constructor(protected readonly options: CustomTypeOptions<S, T>) {
    method describe (line 89) | describe() {
    method isValidSnapshot (line 93) | isValidSnapshot(value: this["C"], context: IValidationContext): IValid...
    method getSnapshot (line 107) | getSnapshot(node: this["N"]): S {
    method instantiate (line 111) | instantiate(
    method reconcile (line 123) | reconcile(current: this["N"], value: S | T, parent: AnyObjectNode, sub...

FILE: src/types/utility-types/enumeration.ts
  type UnionStringArray (line 4) | type UnionStringArray<T extends readonly string[]> = T[number]
  function enumeration (line 33) | function enumeration<T extends string>(

FILE: src/types/utility-types/frozen.ts
  class Frozen (line 23) | class Frozen<T> extends SimpleType<T, T, T> {
    method constructor (line 26) | constructor(private subType?: IAnyType) {
    method describe (line 30) | describe() {
    method instantiate (line 34) | instantiate(
    method isValidSnapshot (line 44) | isValidSnapshot(value: this["C"], context: IValidationContext): IValid...
  function frozen (line 102) | function frozen(arg?: any): any {
  function isFrozenType (line 114) | function isFrozenType(type: unknown): type is ISimpleType<any> {

FILE: src/types/utility-types/identifier.ts
  method constructor (line 21) | constructor(
  method instantiate (line 28) | instantiate(
  method reconcile (line 42) | reconcile(current: this["N"], newValue: this["C"], parent: AnyObjectNode...
  method isValidSnapshot (line 52) | isValidSnapshot(value: this["C"], context: IValidationContext): IValidat...
  class IdentifierType (line 68) | class IdentifierType extends BaseIdentifierType<string> {
    method constructor (line 71) | constructor() {
    method describe (line 75) | describe() {
  class IdentifierNumberType (line 84) | class IdentifierNumberType extends BaseIdentifierType<number> {
    method constructor (line 85) | constructor() {
    method getSnapshot (line 89) | getSnapshot(node: ScalarNode<number, number, number>): number {
    method describe (line 93) | describe() {
  function isIdentifierType (line 138) | function isIdentifierType(
  type ReferenceIdentifier (line 147) | type ReferenceIdentifier = string | number
  function normalizeIdentifier (line 153) | function normalizeIdentifier(id: ReferenceIdentifier): string {
  function isValidIdentifier (line 161) | function isValidIdentifier(id: any): id is ReferenceIdentifier {
  function assertIsValidIdentifier (line 169) | function assertIsValidIdentifier(id: ReferenceIdentifier, argNumber: num...

FILE: src/types/utility-types/late.ts
  class Late (line 16) | class Late<IT extends IAnyType> extends BaseType<
    method flags (line 24) | get flags() {
    method getSubType (line 30) | getSubType(mustSucceed: boolean): IT | undefined {
    method constructor (line 56) | constructor(
    method instantiate (line 63) | instantiate(
    method reconcile (line 72) | reconcile(
    method describe (line 81) | describe() {
    method isValidSnapshot (line 86) | isValidSnapshot(value: this["C"], context: IValidationContext): IValid...
    method isAssignableFrom (line 95) | isAssignableFrom(type: IAnyType) {
    method getSubTypes (line 100) | getSubTypes() {
  function late (line 124) | function late(nameOrType: any, maybeType?: () => IAnyType): IAnyType {
  function isLateType (line 144) | function isLateType(type: unknown): type is IAnyType {

FILE: src/types/utility-types/lazy.ts
  type LazyOptions (line 17) | interface LazyOptions<T extends IType<any, any, any>, U> {
  function lazy (line 22) | function lazy<T extends IType<any, any, any>, U>(
  class Lazy (line 34) | class Lazy<T extends IType<any, any, any>, U> extends SimpleType<T, T, T> {
    method constructor (line 40) | constructor(
    method describe (line 76) | describe() {
    method instantiate (line 80) | instantiate(
    method isValidSnapshot (line 101) | isValidSnapshot(value: this["C"], context: IValidationContext): IValid...
    method reconcile (line 111) | reconcile(current: this["N"], value: T, parent: AnyObjectNode, subpath...

FILE: src/types/utility-types/literal.ts
  class Literal (line 22) | class Literal<T> extends SimpleType<T, T, T> {
    method constructor (line 26) | constructor(value: T) {
    method instantiate (line 31) | instantiate(
    method describe (line 40) | describe() {
    method isValidSnapshot (line 44) | isValidSnapshot(value: this["C"], context: IValidationContext): IValid...
  function literal (line 72) | function literal<S extends Primitives>(value: S): ISimpleType<S> {
  function isLiteralType (line 85) | function isLiteralType(type: unknown): type is ISimpleType<any> {

FILE: src/types/utility-types/maybe.ts
  type IMaybeIType (line 15) | interface IMaybeIType<IT extends IAnyType, C, O>
  type IMaybe (line 19) | interface IMaybe<IT extends IAnyType> extends IMaybeIType<IT, undefined,...
  type IMaybeNull (line 22) | interface IMaybeNull<IT extends IAnyType> extends IMaybeIType<IT, null |...
  function maybe (line 31) | function maybe<IT extends IAnyType>(type: IT): IMaybe<IT> {
  function maybeNull (line 44) | function maybeNull<IT extends IAnyType>(type: IT): IMaybeNull<IT> {

FILE: src/types/utility-types/optional.ts
  type IFunctionReturn (line 19) | type IFunctionReturn<T> = () => T
  type IOptionalValue (line 21) | type IOptionalValue<C, T> = C | IFunctionReturn<C | T>
  type ValidOptionalValue (line 24) | type ValidOptionalValue = string | boolean | number | null | undefined
  type ValidOptionalValues (line 27) | type ValidOptionalValues = [ValidOptionalValue, ...ValidOptionalValue[]]
  class OptionalValue (line 33) | class OptionalValue<
    method flags (line 41) | get flags() {
    method constructor (line 45) | constructor(
    method describe (line 53) | describe() {
    method instantiate (line 57) | instantiate(
    method reconcile (line 75) | reconcile(
    method getDefaultInstanceOrSnapshot (line 91) | getDefaultInstanceOrSnapshot(): this["C"] | this["T"] {
    method isValidSnapshot (line 106) | isValidSnapshot(value: this["C"], context: IValidationContext): IValid...
    method isAssignableFrom (line 115) | isAssignableFrom(type: IAnyType) {
    method getSubTypes (line 119) | getSubTypes() {
  type OptionalDefaultValueOrFunction (line 125) | type OptionalDefaultValueOrFunction<IT extends IAnyType> =
  type IOptionalIType (line 131) | interface IOptionalIType<IT extends IAnyType, OptionalVals extends Valid...
  function checkOptionalPreconditions (line 138) | function checkOptionalPreconditions<IT extends IAnyType>(
  function optional (line 211) | function optional<IT extends IAnyType, OptionalVals extends ValidOptiona...
  function isOptionalType (line 234) | function isOptionalType(type: unknown): type is IOptionalIType<IAnyType,...

FILE: src/types/utility-types/reference.ts
  type OnReferenceInvalidatedEvent (line 36) | type OnReferenceInvalidatedEvent<STN extends IAnyStateTreeNode> = {
  type OnReferenceInvalidated (line 45) | type OnReferenceInvalidated<STN extends IAnyStateTreeNode> = (
  function getInvalidationCause (line 49) | function getInvalidationCause(hook: Hook): "detach" | "destroy" | undefi...
  type ReferenceT (line 61) | type ReferenceT<IT extends IAnyType> = IT["TypeWithoutSTN"] &
  class StoredReference (line 64) | class StoredReference<IT extends IAnyType> {
    method constructor (line 73) | constructor(
    method updateResolvedReference (line 97) | private updateResolvedReference(node: AnyNode) {
    method resolvedValue (line 124) | get resolvedValue(): ReferenceT<IT> {
  class InvalidReferenceError (line 134) | class InvalidReferenceError extends Error {
    method constructor (line 135) | constructor(m: string) {
  method constructor (line 153) | constructor(
  method describe (line 160) | describe() {
  method isAssignableFrom (line 164) | isAssignableFrom(type: IAnyType): boolean {
  method isValidSnapshot (line 168) | isValidSnapshot(value: this["C"], context: IValidationContext): IValidat...
  method fireInvalidated (line 178) | private fireInvalidated(
  method addTargetNodeWatcher (line 220) | private addTargetNodeWatcher(
  method watchTargetNodeForInvalidations (line 254) | protected watchTargetNodeForInvalidations(
  class IdentifierReferenceType (line 341) | class IdentifierReferenceType<IT extends IAnyComplexType> extends BaseRe...
    method constructor (line 342) | constructor(targetType: IT, onInvalidated?: OnReferenceInvalidated<Ref...
    method getValue (line 346) | getValue(storedRefNode: this["N"]) {
    method getSnapshot (line 352) | getSnapshot(storedRefNode: this["N"]) {
    method instantiate (line 357) | instantiate(
    method reconcile (line 379) | reconcile(
  class CustomReferenceType (line 406) | class CustomReferenceType<IT extends IAnyComplexType> extends BaseRefere...
    method constructor (line 407) | constructor(
    method getValue (line 415) | getValue(storedRefNode: this["N"]) {
    method getSnapshot (line 424) | getSnapshot(storedRefNode: this["N"]) {
    method instantiate (line 428) | instantiate(
    method reconcile (line 448) | reconcile(
  type ReferenceOptionsGetSet (line 471) | interface ReferenceOptionsGetSet<IT extends IAnyComplexType> {
  type ReferenceOptionsOnInvalidated (line 476) | interface ReferenceOptionsOnInvalidated<IT extends IAnyComplexType> {
  type ReferenceOptions (line 481) | type ReferenceOptions<IT extends IAnyComplexType> =
  type IReferenceType (line 487) | interface IReferenceType<IT extends IAnyComplexType>
  function reference (line 494) | function reference<IT extends IAnyComplexType>(
  function isReferenceType (line 541) | function isReferenceType(type: unknown): type is IReferenceType<IAnyComp...
  function safeReference (line 577) | function safeReference<IT extends IAnyComplexType>(

FILE: src/types/utility-types/refinement.ts
  class Refinement (line 19) | class Refinement<IT extends IAnyType> extends BaseType<
    method flags (line 25) | get flags() {
    method constructor (line 29) | constructor(
    method describe (line 38) | describe() {
    method instantiate (line 42) | instantiate(
    method isAssignableFrom (line 52) | isAssignableFrom(type: IAnyType) {
    method isValidSnapshot (line 56) | isValidSnapshot(value: this["C"], context: IValidationContext): IValid...
    method reconcile (line 69) | reconcile(
    method getSubTypes (line 78) | getSubTypes() {
  function refinement (line 103) | function refinement(...args: any[]): IAnyType {
  function isRefinementType (line 125) | function isRefinementType(type: unknown): type is IAnyType {

FILE: src/types/utility-types/snapshotProcessor.ts
  type _NotCustomized (line 31) | interface _NotCustomized {
  type _CustomOrOther (line 37) | type _CustomOrOther<Custom, Other> = Custom extends _NotCustomized ? Oth...
  class SnapshotProcessor (line 39) | class SnapshotProcessor<IT extends IAnyType, CustomC, CustomS> extends B...
    method flags (line 45) | get flags() {
    method constructor (line 49) | constructor(
    method describe (line 57) | describe() {
    method preProcessSnapshot (line 61) | private preProcessSnapshot(sn: this["C"]): IT["CreationType"] {
    method preProcessSnapshotSafe (line 68) | private preProcessSnapshotSafe(sn: this["C"]): IT["CreationType"] | ty...
    method postProcessSnapshot (line 76) | private postProcessSnapshot(sn: IT["SnapshotType"], node: this["N"]): ...
    method _fixNode (line 83) | private _fixNode(node: this["N"]): void {
    method instantiate (line 99) | instantiate(
    method reconcile (line 118) | reconcile(
    method getSnapshot (line 136) | getSnapshot(node: this["N"], applyPostProcess: boolean = true): this["...
    method isValidSnapshot (line 141) | isValidSnapshot(value: this["C"], context: IValidationContext): IValid...
    method getSubTypes (line 149) | getSubTypes() {
    method is (line 170) | is(thing: any): thing is any {
    method isAssignableFrom (line 182) | isAssignableFrom(type: IAnyType): boolean {
    method isMatchingSnapshotId (line 186) | isMatchingSnapshotId(current: this["N"], snapshot: this["C"]): boolean {
  function proxyNodeTypeMethods (line 195) | function proxyNodeTypeMethods(
  type ISnapshotProcessor (line 210) | interface ISnapshotProcessor<IT extends IAnyType, CustomC, CustomS>
  type ISnapshotProcessors (line 220) | interface ISnapshotProcessors<IT extends IAnyType, CustomC, CustomS> {
  function snapshotProcessor (line 271) | function snapshotProcessor<

FILE: src/types/utility-types/union.ts
  type ITypeDispatcher (line 22) | type ITypeDispatcher<Types extends IAnyType[]> = (
  type UnionOptions (line 26) | interface UnionOptions<Types extends IAnyType[]> {
  class Union (line 45) | class Union<Types extends IAnyType[]> extends BaseType<
    method flags (line 53) | get flags() {
    method constructor (line 63) | constructor(
    method isAssignableFrom (line 78) | isAssignableFrom(type: IAnyType) {
    method describe (line 82) | describe() {
    method instantiate (line 86) | instantiate(
    method reconcile (line 97) | reconcile(
    method determineType (line 108) | determineType(
    method isValidSnapshot (line 129) | isValidSnapshot(value: this["C"], context: IValidationContext): IValid...
    method getSubTypes (line 153) | getSubTypes() {
  type _CustomCSProcessor (line 162) | type _CustomCSProcessor<T> =
  type ITypeUnion (line 166) | interface ITypeUnion<C, S, T>
  type IUnionType (line 169) | type IUnionType<Types extends IAnyType[]> = ITypeUnion<
  function union (line 187) | function union<Types extends IAnyType[]>(
  function isUnionType (line 218) | function isUnionType(type: unknown): type is IUnionType<IAnyType[]> {

FILE: src/utils.ts
  constant EMPTY_ARRAY (line 15) | const EMPTY_ARRAY: ReadonlyArray<any> = Object.freeze([])
  constant EMPTY_OBJECT (line 21) | const EMPTY_OBJECT: {} = Object.freeze({})
  type IDisposer (line 35) | type IDisposer = () => void
  class MstError (line 41) | class MstError extends Error {
    method constructor (line 42) | constructor(message = "Illegal state") {
  function identity (line 51) | function identity(_: any): any {
  function noop (line 59) | function noop() {}
  function isFloat (line 71) | function isFloat(val: any) {
  function isFinite (line 79) | function isFinite(val: any) {
  function isArray (line 87) | function isArray(val: any): val is any[] {
  function asArray (line 95) | function asArray<T>(val: undefined | null | T | T[] | ReadonlyArray<T>):...
  function extend (line 125) | function extend(a: any, ...b: any[]) {
  function isPlainObject (line 137) | function isPlainObject(value: any): value is { [k: string]: any } {
  function isMutable (line 148) | function isMutable(value: any) {
  function isPrimitive (line 161) | function isPrimitive(value: any, includeDate = true): value is Primitives {
  function freeze (line 178) | function freeze<T>(value: T): T {
  function deepFreeze (line 188) | function deepFreeze<T>(value: T): T {
  function isSerializable (line 210) | function isSerializable(value: any) {
  function defineProperty (line 218) | function defineProperty(object: any, key: PropertyKey, descriptor: Prope...
  function addHiddenFinalProp (line 228) | function addHiddenFinalProp(object: any, propName: string, value: any) {
  function addHiddenWritableProp (line 241) | function addHiddenWritableProp(object: any, propName: string, value: any) {
  type ArgumentTypes (line 254) | type ArgumentTypes<F extends Function> = F extends (...args: infer A) =>...
  class EventHandler (line 260) | class EventHandler<F extends Function> {
    method hasSubscribers (line 263) | get hasSubscribers(): boolean {
    method register (line 267) | register(fn: F, atTheBeginning = false): IDisposer {
    method has (line 278) | has(fn: F): boolean {
    method unregister (line 282) | unregister(fn: F) {
    method clear (line 289) | clear() {
    method emit (line 293) | emit(...args: ArgumentTypes<F>) {
  class EventHandlers (line 304) | class EventHandlers<E extends { [k: string]: Function }> {
    method hasSubscribers (line 307) | hasSubscribers(event: keyof E): boolean {
    method register (line 312) | register<N extends keyof E>(event: N, fn: E[N], atTheBeginning = false...
    method has (line 323) | has<N extends keyof E>(event: N, fn: E[N]): boolean {
    method unregister (line 328) | unregister<N extends keyof E>(event: N, fn: E[N]) {
    method clear (line 335) | clear<N extends keyof E>(event: N) {
    method clearAll (line 341) | clearAll() {
    method emit (line 345) | emit<N extends keyof E>(event: N, ...args: ArgumentTypes<E[N]>) {
  function hasOwnProperty (line 359) | function hasOwnProperty(object: Object, propName: string) {
  function argsToArray (line 367) | function argsToArray(args: IArguments): any[] {
  function stringStartsWith (line 377) | function stringStartsWith(str: string, beginning: string) {
  type DeprecatedFunction (line 385) | type DeprecatedFunction = Function & { ids?: { [id: string]: true } }
  function warnError (line 407) | function warnError(msg: string) {
  function isTypeCheckingEnabled (line 414) | function isTypeCheckingEnabled() {
  function devMode (line 425) | function devMode() {
  function assertArg (line 433) | function assertArg<T>(
  function assertIsFunction (line 453) | function assertIsFunction(value: Function, argNumber: number | number[]) {
  function assertIsNumber (line 461) | function assertIsNumber(
  function assertIsString (line 480) | function assertIsString(value: string, argNumber: number | number[], can...
  function setImmediateWithFallback (line 491) | function setImmediateWithFallback(fn: (...args: any[]) => void) {

FILE: website/core/Footer.js
  class Footer (line 10) | class Footer extends React.Component {
    method docUrl (line 11) | docUrl(doc, language) {
    method pageUrl (line 19) | pageUrl(doc, language) {
    method render (line 24) | render() {
Condensed preview — 206 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,581K chars).
[
  {
    "path": ".circleci/config.yml",
    "chars": 2654,
    "preview": "version: 2.1\n\nexecutors:\n  my-executor:\n    docker:\n      - image: cimg/node:14.18.1\n        environment:\n          CI: "
  },
  {
    "path": ".dockerignore",
    "chars": 21,
    "preview": "*/node_modules\n*.log\n"
  },
  {
    "path": ".gitattributes",
    "chars": 66,
    "preview": "* text=auto\n\n*.ts text eol=lf\n*.json text eol=lf\n*.md text eol=lf\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug-report.md",
    "chars": 800,
    "preview": "---\nname: Bug report\nabout: I think something is not working as it should\n---\n\n<!-- Not following the template might res"
  },
  {
    "path": ".github/lock.yml",
    "chars": 932,
    "preview": "# Configuration for Lock Threads - https://github.com/dessant/lock-threads\n\n# Number of days of inactivity before a clos"
  },
  {
    "path": ".github/pull_request_template.md",
    "chars": 610,
    "preview": "## What does this PR do and why?\n\n<!--\nTry to complete the sentence: \"If this pull request is approved, it will...\",\nand"
  },
  {
    "path": ".github/stale.yml",
    "chars": 1088,
    "preview": "# Number of days of inactivity before an issue becomes stale\ndaysUntilStale: 10\n# Number of days of inactivity before a "
  },
  {
    "path": ".gitignore",
    "chars": 168,
    "preview": "node_modules\n*.log\nlib\ndist\ncoverage\n.nyc_output\n.idea\npackage-lock.json\n.prettierignore\n.vscode\n.editorconfig\n/test-res"
  },
  {
    "path": ".husky/pre-commit",
    "chars": 62,
    "preview": "#!/bin/sh\n. \"$(dirname \"$0\")/_/husky.sh\"\n\nbun run lint-staged\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "chars": 5089,
    "preview": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nWe as members, contributors, and leaders pledge to make participa"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 6291,
    "preview": "# Contributing to MobX-State-Tree\n\nWelcome to MobX-State-Tree! We're stoked that you want to contribute to our open-sour"
  },
  {
    "path": "Dockerfile",
    "chars": 148,
    "preview": "FROM node:8.11.4\n\nWORKDIR /app/website\n\nEXPOSE 3000 35729\nCOPY ./docs /app/docs\nCOPY ./website /app/website\nRUN yarn ins"
  },
  {
    "path": "ISSUE_TEMPLATE.md",
    "chars": 162,
    "preview": "**If your issue isn't a bug report, please consider using discussion threads instead of opening an issue: https://github"
  },
  {
    "path": "LICENSE",
    "chars": 1074,
    "preview": "MIT License\n\nCopyright (c) 2016 Michel Weststrate\n\nPermission is hereby granted, free of charge, to any person obtaining"
  },
  {
    "path": "README.md",
    "chars": 4433,
    "preview": "<img src=\"website/static/img/mobx-state-tree-logo-gradient.png\" alt=\"logo\" height=\"120\" align=\"right\" />\n\n# mobx-state-t"
  },
  {
    "path": "SECURITY.md",
    "chars": 193,
    "preview": "## Security contact information\n\nTo report a security vulnerability, please use the\n[Tidelift security contact](https://"
  },
  {
    "path": "__tests__/core/1525.test.ts",
    "chars": 1219,
    "preview": "import { types, Instance } from \"../../src/index\"\nimport { describe, it } from \"bun:test\"\n\ndescribe(\"1525. Model instanc"
  },
  {
    "path": "__tests__/core/1664.test.ts",
    "chars": 1498,
    "preview": "import { types as t } from \"../../src/index\"\nimport { describe, test } from \"bun:test\"\n\ndescribe(\"1664. Array and model "
  },
  {
    "path": "__tests__/core/2230.test.ts",
    "chars": 5111,
    "preview": "//github.com/mobxjs/mobx-state-tree/issues/2230\nimport { describe, test } from \"bun:test\"\nimport { types, Instance } fro"
  },
  {
    "path": "__tests__/core/__snapshots__/async.test.ts.snap",
    "chars": 23223,
    "preview": "// Bun Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`can handle erroring actions 1`] = `\n[\n  {\n    \"allParentIds\": [],\n  "
  },
  {
    "path": "__tests__/core/__snapshots__/custom-type.test.ts.snap",
    "chars": 1520,
    "preview": "// Bun Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`reassignments will work 1`] = `\n[\n  {\n    \"balance\": \"2.5\",\n    \"las"
  },
  {
    "path": "__tests__/core/__snapshots__/reference-custom.test.ts.snap",
    "chars": 2045,
    "preview": "// Bun Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`it should support custom references - adv 1`] = `\n[\n  \"1\",\n  \"2\",\n  "
  },
  {
    "path": "__tests__/core/action.test.ts",
    "chars": 12048,
    "preview": "import { configure } from \"mobx\"\nimport {\n    recordActions,\n    types,\n    getSnapshot,\n    onAction,\n    applyPatch,\n "
  },
  {
    "path": "__tests__/core/actionTrackingMiddleware2.test.ts",
    "chars": 11745,
    "preview": "import {\n    addMiddleware,\n    createActionTrackingMiddleware2,\n    types,\n    flow,\n    IActionTrackingMiddleware2Call"
  },
  {
    "path": "__tests__/core/api.test.ts",
    "chars": 3637,
    "preview": "import { expect, test } from \"bun:test\"\nimport { readFileSync } from \"fs\"\nimport * as mst from \"../../src\"\n\nfunction str"
  },
  {
    "path": "__tests__/core/array.test.ts",
    "chars": 19378,
    "preview": "import {\n    unprotect,\n    onSnapshot,\n    onPatch,\n    clone,\n    isAlive,\n    applyPatch,\n    getPath,\n    applySnaps"
  },
  {
    "path": "__tests__/core/async.test.ts",
    "chars": 11954,
    "preview": "import { configure, reaction } from \"mobx\"\nimport {\n    addMiddleware,\n    decorate,\n    destroy,\n    flow,\n    IMiddlew"
  },
  {
    "path": "__tests__/core/bigint.test.ts",
    "chars": 13361,
    "preview": "import { t } from \"../../src\"\nimport { Hook, NodeLifeCycle } from \"../../src/internal\"\nimport { describe, it, expect, te"
  },
  {
    "path": "__tests__/core/boolean.test.ts",
    "chars": 12248,
    "preview": "import { t } from \"../../src\"\nimport { Hook, NodeLifeCycle } from \"../../src/internal\"\nimport { describe, expect, it, te"
  },
  {
    "path": "__tests__/core/boxes-store.test.ts",
    "chars": 5277,
    "preview": "import { values } from \"mobx\"\nimport {\n    types,\n    getParent,\n    hasParent,\n    recordPatches,\n    unprotect,\n    ge"
  },
  {
    "path": "__tests__/core/circular1.test.ts",
    "chars": 916,
    "preview": "import { types } from \"../../src\"\nimport { LateTodo2, LateStore2 } from \"./circular2.test\"\nimport { expect, test } from "
  },
  {
    "path": "__tests__/core/circular2.test.ts",
    "chars": 916,
    "preview": "import { types } from \"../../src\"\nimport { LateTodo1, LateStore1 } from \"./circular1.test\"\nimport { expect, test } from "
  },
  {
    "path": "__tests__/core/custom-type.test.ts",
    "chars": 6321,
    "preview": "import {\n    types,\n    recordPatches,\n    onSnapshot,\n    unprotect,\n    applySnapshot,\n    applyPatch,\n    SnapshotOut"
  },
  {
    "path": "__tests__/core/date.test.ts",
    "chars": 13378,
    "preview": "import { t } from \"../../src\"\nimport { Hook, NodeLifeCycle } from \"../../src/internal\"\nimport { describe, expect, it, te"
  },
  {
    "path": "__tests__/core/deprecated.test.ts",
    "chars": 1714,
    "preview": "import { deprecated } from \"../../src/utils\"\nimport { flow, createFlowSpawner } from \"../../src/core/flow\"\nimport { proc"
  },
  {
    "path": "__tests__/core/enum.test.ts",
    "chars": 3090,
    "preview": "import { types, unprotect } from \"../../src\"\nimport { expect, test } from \"bun:test\"\n\nenum ColorEnum {\n    Red = \"Red\",\n"
  },
  {
    "path": "__tests__/core/env.test.ts",
    "chars": 10325,
    "preview": "import { configure } from \"mobx\"\nimport {\n    types,\n    hasEnv,\n    getEnv,\n    clone,\n    detach,\n    unprotect,\n    w"
  },
  {
    "path": "__tests__/core/frozen.test.ts",
    "chars": 2864,
    "preview": "import { getSnapshot, types, unprotect } from \"../../src\"\nimport { expect, test } from \"bun:test\"\n\ntest(\"it should accep"
  },
  {
    "path": "__tests__/core/hooks.test.ts",
    "chars": 13605,
    "preview": "import {\n    addDisposer,\n    destroy,\n    detach,\n    types,\n    unprotect,\n    getSnapshot,\n    applySnapshot,\n    onS"
  },
  {
    "path": "__tests__/core/identifier.test.ts",
    "chars": 10306,
    "preview": "import {\n    types,\n    tryResolve,\n    resolvePath,\n    SnapshotOrInstance,\n    IAnyModelType,\n    IAnyComplexType,\n   "
  },
  {
    "path": "__tests__/core/jsonpatch.test.ts",
    "chars": 15078,
    "preview": "import {\n    getSnapshot,\n    unprotect,\n    recordPatches,\n    types,\n    IType,\n    IJsonPatch,\n    Instance,\n    cast"
  },
  {
    "path": "__tests__/core/late.test.ts",
    "chars": 3873,
    "preview": "import { types, typecheck, IAnyModelType } from \"../../src\"\nimport { expect, spyOn, test } from \"bun:test\"\n\nif (process."
  },
  {
    "path": "__tests__/core/lazy.test.ts",
    "chars": 2930,
    "preview": "import { when } from \"mobx\"\nimport { getRoot, types } from \"../../src\"\nimport { expect, test } from \"bun:test\"\n\ninterfac"
  },
  {
    "path": "__tests__/core/literal.test.ts",
    "chars": 1592,
    "preview": "import { types } from \"../../src\"\nimport { expect, test } from \"bun:test\"\n\nif (process.env.NODE_ENV !== \"production\") {\n"
  },
  {
    "path": "__tests__/core/map.test.ts",
    "chars": 19742,
    "preview": "import { configure } from \"mobx\"\nimport {\n    onSnapshot,\n    onPatch,\n    applyPatch,\n    applySnapshot,\n    getSnapsho"
  },
  {
    "path": "__tests__/core/model.test.ts",
    "chars": 25689,
    "preview": "import { applySnapshot, getSnapshot, types } from \"../../src\"\nimport { Hook } from \"../../src/internal\"\nimport { describ"
  },
  {
    "path": "__tests__/core/name.test.ts",
    "chars": 467,
    "preview": "import { types } from \"../../src\"\nimport { getDebugName } from \"mobx\"\nimport { expect, test } from \"bun:test\"\n\ntest(\"it "
  },
  {
    "path": "__tests__/core/node.test.ts",
    "chars": 12430,
    "preview": "import {\n    getPath,\n    getSnapshot,\n    getParent,\n    hasParent,\n    getRoot,\n    getIdentifier,\n    getPathParts,\n "
  },
  {
    "path": "__tests__/core/number.test.ts",
    "chars": 12353,
    "preview": "import { t } from \"../../src\"\nimport { Hook, NodeLifeCycle } from \"../../src/internal\"\nimport { describe, it, expect, te"
  },
  {
    "path": "__tests__/core/object-node.test.ts",
    "chars": 77500,
    "preview": "import { t } from \"../../src/index\"\nimport { Hook, ObjectNode, onPatch, unprotect } from \"../../src/internal\"\nimport { d"
  },
  {
    "path": "__tests__/core/object.test.ts",
    "chars": 34675,
    "preview": "import {\n    destroy,\n    detach,\n    onSnapshot,\n    onPatch,\n    onAction,\n    applyPatch,\n    applyAction,\n    applyS"
  },
  {
    "path": "__tests__/core/optimizations.test.ts",
    "chars": 1459,
    "preview": "import { getSnapshot, applySnapshot, unprotect, types } from \"../../src\"\nimport { expect, test } from \"bun:test\"\n\ntest(\""
  },
  {
    "path": "__tests__/core/optional-extension.test.ts",
    "chars": 9027,
    "preview": "import { getSnapshot, types, unprotect } from \"../../src\"\nimport { describe, expect, test } from \"bun:test\"\n\ndescribe(\"n"
  },
  {
    "path": "__tests__/core/optional.test.ts",
    "chars": 5150,
    "preview": "import { getSnapshot, types, unprotect, applySnapshot, cast } from \"../../src\"\nimport { expect, test } from \"bun:test\"\n\n"
  },
  {
    "path": "__tests__/core/parent-properties.test.ts",
    "chars": 3976,
    "preview": "import { types, getEnv, getParent, getPath, Instance } from \"../../src\"\nimport { expect, test } from \"bun:test\"\n\nconst C"
  },
  {
    "path": "__tests__/core/pointer.test.ts",
    "chars": 2856,
    "preview": "import { types, unprotect, IAnyModelType, castToReferenceSnapshot } from \"../../src\"\nimport { expect, test } from \"bun:t"
  },
  {
    "path": "__tests__/core/primitives.test.ts",
    "chars": 4796,
    "preview": "import { isFinite, isFloat, isInteger } from \"../../src/utils\"\nimport { types, applySnapshot, getSnapshot } from \"../../"
  },
  {
    "path": "__tests__/core/protect.test.ts",
    "chars": 4292,
    "preview": "import { protect, unprotect, applySnapshot, types, isProtected, getParent, cast } from \"../../src\"\nimport { expect, test"
  },
  {
    "path": "__tests__/core/recordPatches.test.ts",
    "chars": 9731,
    "preview": "import {\n    getSnapshot,\n    unprotect,\n    recordPatches,\n    types,\n    IType,\n    IJsonPatch,\n    Instance,\n    cast"
  },
  {
    "path": "__tests__/core/reference-custom.test.ts",
    "chars": 8618,
    "preview": "import { reaction, when, values } from \"mobx\"\nimport {\n    types,\n    recordPatches,\n    getSnapshot,\n    applySnapshot,"
  },
  {
    "path": "__tests__/core/reference-onInvalidated.test.ts",
    "chars": 15677,
    "preview": "import {\n    types,\n    OnReferenceInvalidated,\n    Instance,\n    ReferenceIdentifier,\n    IAnyStateTreeNode,\n    unprot"
  },
  {
    "path": "__tests__/core/reference.test.ts",
    "chars": 34328,
    "preview": "import { reaction, autorun, isObservable, configure } from \"mobx\"\nimport {\n    types,\n    getSnapshot,\n    applySnapshot"
  },
  {
    "path": "__tests__/core/refinement.test.ts",
    "chars": 2567,
    "preview": "import { getSnapshot, types } from \"../../src\"\nimport { expect, test } from \"bun:test\"\n\ntest(\"it should allow if type an"
  },
  {
    "path": "__tests__/core/reflection.test.ts",
    "chars": 9086,
    "preview": "import {\n    types,\n    getMembers,\n    getPropertyMembers,\n    IAnyStateTreeNode,\n    getType,\n    IAnyModelType,\n    I"
  },
  {
    "path": "__tests__/core/snapshotProcessor.test.ts",
    "chars": 30037,
    "preview": "import { observable } from \"mobx\"\nimport {\n    types,\n    getSnapshot,\n    unprotect,\n    cast,\n    detach,\n    clone,\n "
  },
  {
    "path": "__tests__/core/string.test.ts",
    "chars": 12385,
    "preview": "import { types } from \"../../src\"\nimport { Hook, NodeLifeCycle } from \"../../src/internal\"\nimport { describe, expect, it"
  },
  {
    "path": "__tests__/core/this.test.ts",
    "chars": 2593,
    "preview": "import { types } from \"../../src\"\nimport { isObservableProp, isComputedProp } from \"mobx\"\nimport { expect, test } from \""
  },
  {
    "path": "__tests__/core/type-system.test.ts",
    "chars": 43300,
    "preview": "import { describe, expect, test } from \"bun:test\"\nimport {\n    IAnyType,\n    IType,\n    Instance,\n    ModelPrimitive,\n  "
  },
  {
    "path": "__tests__/core/union.test.ts",
    "chars": 11667,
    "preview": "import { configure } from \"mobx\"\nimport {\n    types,\n    hasParent,\n    tryResolve,\n    getSnapshot,\n    applySnapshot,\n"
  },
  {
    "path": "__tests__/core/volatile.test.ts",
    "chars": 4378,
    "preview": "import { types, getSnapshot, recordPatches, unprotect } from \"../../src\"\nimport { reaction, isObservableProp, isObservab"
  },
  {
    "path": "__tests__/perf/fixture-data.skip.ts",
    "chars": 1412,
    "preview": "import { rando, createHeros, createMonsters, createTreasure } from \"./fixtures/fixture-data\"\nimport { Hero, Monster, Tre"
  },
  {
    "path": "__tests__/perf/fixture-models.skip.ts",
    "chars": 1463,
    "preview": "import { Hero, Monster, Treasure } from \"./fixtures/fixture-models\"\nimport { expect, test } from \"bun:test\"\nconst mst = "
  },
  {
    "path": "__tests__/perf/fixtures/fixture-data.ts",
    "chars": 2965,
    "preview": "import { HeroRoles } from \"./fixture-models\"\n\n/**\n * Creates data containing very few fields.\n *\n * @param count The num"
  },
  {
    "path": "__tests__/perf/fixtures/fixture-models.ts",
    "chars": 2344,
    "preview": "const mst = require(\"../../../dist/mobx-state-tree.umd\")\nconst { types } = mst\n\n// tiny\nexport const Treasure = types.mo"
  },
  {
    "path": "__tests__/perf/perf.skip.ts",
    "chars": 1101,
    "preview": "import { smallScenario, mediumScenario, largeScenario } from \"./scenarios\"\nimport { start } from \"./timer\"\nimport { expe"
  },
  {
    "path": "__tests__/perf/report.ts",
    "chars": 2519,
    "preview": "import { smallScenario, mediumScenario, largeScenario } from \"./scenarios\"\n\n// here's what we'll be testing\nconst plan ="
  },
  {
    "path": "__tests__/perf/scenarios.ts",
    "chars": 1638,
    "preview": "import { start } from \"./timer\"\nimport { Treasure, Hero, Monster } from \"./fixtures/fixture-models\"\nimport { createTreas"
  },
  {
    "path": "__tests__/perf/timer.ts",
    "chars": 622,
    "preview": "/**\n * Start a timer which return a function, which when called show the\n * number of milliseconds since it started.\n *\n"
  },
  {
    "path": "__tests__/setup.ts",
    "chars": 417,
    "preview": "import { beforeEach, afterEach, mock } from \"bun:test\"\nimport { resetNextActionId, setLivelinessChecking } from \"../src/"
  },
  {
    "path": "__tests__/tsconfig.json",
    "chars": 249,
    "preview": "{\n  \"extends\": \"../tsconfig.json\",\n  \"compilerOptions\": {\n    \"rootDir\": \"../\",\n    \"module\": \"commonjs\",\n    \"lib\": [\"e"
  },
  {
    "path": "__tests__/utils.test.ts",
    "chars": 698,
    "preview": "import { MstError } from \"../src/utils\"\nimport { describe, expect, test } from \"bun:test\"\n\ndescribe(\"MstError custom err"
  },
  {
    "path": "bunfig.toml",
    "chars": 63,
    "preview": "[test]\nroot = \"./__tests__\"\npreload = [\"./__tests__/setup.ts\"]\n"
  },
  {
    "path": "changelog.md",
    "chars": 53596,
    "preview": "The manually-updated changelog has been discontinued. For versions > 4.0.0, go here to view changes:\n\n[https://github.co"
  },
  {
    "path": "docker-compose.yml",
    "chars": 497,
    "preview": "version: \"3\"\n\nservices:\n  docusaurus:\n    build: .\n    ports:\n      - 3000:3000\n      - 35729:35729\n    volumes:\n      -"
  },
  {
    "path": "docs/.gitattributes",
    "chars": 52,
    "preview": "/API/**/* -diff -merge\n/API/**/* linguist-generated\n"
  },
  {
    "path": "docs/API/index.md",
    "chars": 146328,
    "preview": "---\nid: \"index\"\ntitle: \"mobx-state-tree - v7.0.2\"\nsidebar_label: \"Globals\"\n---\n\n[mobx-state-tree - v7.0.2](index.md)\n\n##"
  },
  {
    "path": "docs/API/interfaces/customtypeoptions.md",
    "chars": 2267,
    "preview": "---\nid: \"customtypeoptions\"\ntitle: \"CustomTypeOptions\"\nsidebar_label: \"CustomTypeOptions\"\n---\n\n[mobx-state-tree - v7.0.2"
  },
  {
    "path": "docs/API/interfaces/functionwithflag.md",
    "chars": 4810,
    "preview": "---\nid: \"functionwithflag\"\ntitle: \"FunctionWithFlag\"\nsidebar_label: \"FunctionWithFlag\"\n---\n\n[mobx-state-tree - v7.0.2](."
  },
  {
    "path": "docs/API/interfaces/iactioncontext.md",
    "chars": 1877,
    "preview": "---\nid: \"iactioncontext\"\ntitle: \"IActionContext\"\nsidebar_label: \"IActionContext\"\n---\n\n[mobx-state-tree - v7.0.2](../inde"
  },
  {
    "path": "docs/API/interfaces/iactionrecorder.md",
    "chars": 1592,
    "preview": "---\nid: \"iactionrecorder\"\ntitle: \"IActionRecorder\"\nsidebar_label: \"IActionRecorder\"\n---\n\n[mobx-state-tree - v7.0.2](../i"
  },
  {
    "path": "docs/API/interfaces/iactiontrackingmiddleware2call.md",
    "chars": 1029,
    "preview": "---\nid: \"iactiontrackingmiddleware2call\"\ntitle: \"IActionTrackingMiddleware2Call\"\nsidebar_label: \"IActionTrackingMiddlewa"
  },
  {
    "path": "docs/API/interfaces/iactiontrackingmiddleware2hooks.md",
    "chars": 1794,
    "preview": "---\nid: \"iactiontrackingmiddleware2hooks\"\ntitle: \"IActionTrackingMiddleware2Hooks\"\nsidebar_label: \"IActionTrackingMiddle"
  },
  {
    "path": "docs/API/interfaces/iactiontrackingmiddlewarehooks.md",
    "chars": 3230,
    "preview": "---\nid: \"iactiontrackingmiddlewarehooks\"\ntitle: \"IActionTrackingMiddlewareHooks\"\nsidebar_label: \"IActionTrackingMiddlewa"
  },
  {
    "path": "docs/API/interfaces/ianycomplextype.md",
    "chars": 3479,
    "preview": "---\nid: \"ianycomplextype\"\ntitle: \"IAnyComplexType\"\nsidebar_label: \"IAnyComplexType\"\n---\n\n[mobx-state-tree - v7.0.2](../i"
  },
  {
    "path": "docs/API/interfaces/ianymodeltype.md",
    "chars": 9449,
    "preview": "---\nid: \"ianymodeltype\"\ntitle: \"IAnyModelType\"\nsidebar_label: \"IAnyModelType\"\n---\n\n[mobx-state-tree - v7.0.2](../index.m"
  },
  {
    "path": "docs/API/interfaces/ianytype.md",
    "chars": 3372,
    "preview": "---\nid: \"ianytype\"\ntitle: \"IAnyType\"\nsidebar_label: \"IAnyType\"\n---\n\n[mobx-state-tree - v7.0.2](../index.md) › [IAnyType]"
  },
  {
    "path": "docs/API/interfaces/ihooks.md",
    "chars": 1313,
    "preview": "---\nid: \"ihooks\"\ntitle: \"IHooks\"\nsidebar_label: \"IHooks\"\n---\n\n[mobx-state-tree - v7.0.2](../index.md) › [IHooks](ihooks."
  },
  {
    "path": "docs/API/interfaces/ijsonpatch.md",
    "chars": 936,
    "preview": "---\nid: \"ijsonpatch\"\ntitle: \"IJsonPatch\"\nsidebar_label: \"IJsonPatch\"\n---\n\n[mobx-state-tree - v7.0.2](../index.md) › [IJs"
  },
  {
    "path": "docs/API/interfaces/imiddlewareevent.md",
    "chars": 3713,
    "preview": "---\nid: \"imiddlewareevent\"\ntitle: \"IMiddlewareEvent\"\nsidebar_label: \"IMiddlewareEvent\"\n---\n\n[mobx-state-tree - v7.0.2](."
  },
  {
    "path": "docs/API/interfaces/imodelreflectiondata.md",
    "chars": 2067,
    "preview": "---\nid: \"imodelreflectiondata\"\ntitle: \"IModelReflectionData\"\nsidebar_label: \"IModelReflectionData\"\n---\n\n[mobx-state-tree"
  },
  {
    "path": "docs/API/interfaces/imodelreflectionpropertiesdata.md",
    "chars": 929,
    "preview": "---\nid: \"imodelreflectionpropertiesdata\"\ntitle: \"IModelReflectionPropertiesData\"\nsidebar_label: \"IModelReflectionPropert"
  },
  {
    "path": "docs/API/interfaces/imodeltype.md",
    "chars": 9095,
    "preview": "---\nid: \"imodeltype\"\ntitle: \"IModelType\"\nsidebar_label: \"IModelType\"\n---\n\n[mobx-state-tree - v7.0.2](../index.md) › [IMo"
  },
  {
    "path": "docs/API/interfaces/ipatchrecorder.md",
    "chars": 2487,
    "preview": "---\nid: \"ipatchrecorder\"\ntitle: \"IPatchRecorder\"\nsidebar_label: \"IPatchRecorder\"\n---\n\n[mobx-state-tree - v7.0.2](../inde"
  },
  {
    "path": "docs/API/interfaces/ireversiblejsonpatch.md",
    "chars": 1389,
    "preview": "---\nid: \"ireversiblejsonpatch\"\ntitle: \"IReversibleJsonPatch\"\nsidebar_label: \"IReversibleJsonPatch\"\n---\n\n[mobx-state-tree"
  },
  {
    "path": "docs/API/interfaces/iserializedactioncall.md",
    "chars": 980,
    "preview": "---\nid: \"iserializedactioncall\"\ntitle: \"ISerializedActionCall\"\nsidebar_label: \"ISerializedActionCall\"\n---\n\n[mobx-state-t"
  },
  {
    "path": "docs/API/interfaces/isimpletype.md",
    "chars": 3489,
    "preview": "---\nid: \"isimpletype\"\ntitle: \"ISimpleType\"\nsidebar_label: \"ISimpleType\"\n---\n\n[mobx-state-tree - v7.0.2](../index.md) › ["
  },
  {
    "path": "docs/API/interfaces/isnapshotprocessor.md",
    "chars": 4007,
    "preview": "---\nid: \"isnapshotprocessor\"\ntitle: \"ISnapshotProcessor\"\nsidebar_label: \"ISnapshotProcessor\"\n---\n\n[mobx-state-tree - v7."
  },
  {
    "path": "docs/API/interfaces/isnapshotprocessors.md",
    "chars": 1614,
    "preview": "---\nid: \"isnapshotprocessors\"\ntitle: \"ISnapshotProcessors\"\nsidebar_label: \"ISnapshotProcessors\"\n---\n\n[mobx-state-tree - "
  },
  {
    "path": "docs/API/interfaces/itype.md",
    "chars": 3127,
    "preview": "---\nid: \"itype\"\ntitle: \"IType\"\nsidebar_label: \"IType\"\n---\n\n[mobx-state-tree - v7.0.2](../index.md) › [IType](itype.md)\n\n"
  },
  {
    "path": "docs/API/interfaces/ivalidationcontextentry.md",
    "chars": 956,
    "preview": "---\nid: \"ivalidationcontextentry\"\ntitle: \"IValidationContextEntry\"\nsidebar_label: \"IValidationContextEntry\"\n---\n\n[mobx-s"
  },
  {
    "path": "docs/API/interfaces/ivalidationerror.md",
    "chars": 1116,
    "preview": "---\nid: \"ivalidationerror\"\ntitle: \"IValidationError\"\nsidebar_label: \"IValidationError\"\n---\n\n[mobx-state-tree - v7.0.2](."
  },
  {
    "path": "docs/API/interfaces/referenceoptionsgetset.md",
    "chars": 1422,
    "preview": "---\nid: \"referenceoptionsgetset\"\ntitle: \"ReferenceOptionsGetSet\"\nsidebar_label: \"ReferenceOptionsGetSet\"\n---\n\n[mobx-stat"
  },
  {
    "path": "docs/API/interfaces/referenceoptionsoninvalidated.md",
    "chars": 746,
    "preview": "---\nid: \"referenceoptionsoninvalidated\"\ntitle: \"ReferenceOptionsOnInvalidated\"\nsidebar_label: \"ReferenceOptionsOnInvalid"
  },
  {
    "path": "docs/API/interfaces/unionoptions.md",
    "chars": 1119,
    "preview": "---\nid: \"unionoptions\"\ntitle: \"UnionOptions\"\nsidebar_label: \"UnionOptions\"\n---\n\n[mobx-state-tree - v7.0.2](../index.md) "
  },
  {
    "path": "docs/API_header.md",
    "chars": 446,
    "preview": "# Mobx-State-Tree API reference guide\n\n_This reference guide lists all methods exposed by MST. Contributions like lingui"
  },
  {
    "path": "docs/compare/context-reducer-vs-mobx-state-tree.md",
    "chars": 29946,
    "preview": "---\nid: context-reducer-vs-mobx-state-tree\ntitle: React Context vs. MobX-State-Tree\n---\n\nIf you're using React, you have"
  },
  {
    "path": "docs/concepts/actions.md",
    "chars": 3530,
    "preview": "---\nid: actions\ntitle: Actions\n---\n\n<div id=\"codefund\"></div>\n\n<details>\n    <summary style=\"color: white; background:#f"
  },
  {
    "path": "docs/concepts/async-actions.md",
    "chars": 7914,
    "preview": "---\nid: async-actions\ntitle: Asynchronous actions\n---\n\n<div id=\"codefund\"></div>\n\n<details>\n    <summary style=\"color: w"
  },
  {
    "path": "docs/concepts/dependency-injection.md",
    "chars": 1535,
    "preview": "---\nid: dependency-injection\ntitle: Dependency Injection\n---\n\n<div id=\"codefund\"></div>\n\nWhen creating a new state tree "
  },
  {
    "path": "docs/concepts/listeners.md",
    "chars": 2073,
    "preview": "---\nid: listeners\ntitle: Listening to observables, snapshots, patches and actions\nsidebar_label: Listening to changes\n--"
  },
  {
    "path": "docs/concepts/middleware.md",
    "chars": 6249,
    "preview": "---\nid: middleware\ntitle: Middleware\n---\n\n<div id=\"codefund\"></div>\n\nMiddlewares can be used to intercept any action on "
  },
  {
    "path": "docs/concepts/patches.md",
    "chars": 1805,
    "preview": "---\nid: patches\ntitle: Patches\n---\n\n<div id=\"codefund\"></div>\n\n<details>\n    <summary style=\"color: white; background:#f"
  },
  {
    "path": "docs/concepts/react.md",
    "chars": 1282,
    "preview": "---\nid: using-react\ntitle: React and MST\n---\n\n<div id=\"codefund\"></div>\n\n<details>\n    <summary style=\"color: white; bac"
  },
  {
    "path": "docs/concepts/reconciliation.md",
    "chars": 695,
    "preview": "---\nid: reconciliation\ntitle: Reconciliation\n---\n\n<div id=\"codefund\"></div>\n\n-   When applying snapshots, MST will alway"
  },
  {
    "path": "docs/concepts/references.md",
    "chars": 7899,
    "preview": "---\nid: references\ntitle: Identifiers and references\n---\n\n<div id=\"codefund\"></div>\n\n<details>\n    <summary style=\"color"
  },
  {
    "path": "docs/concepts/snapshots.md",
    "chars": 3358,
    "preview": "---\nid: snapshots\ntitle: Snapshots\n---\n\n<div id=\"codefund\"></div>\n\n<details>\n    <summary style=\"color: white; backgroun"
  },
  {
    "path": "docs/concepts/trees.md",
    "chars": 11083,
    "preview": "---\nid: trees\ntitle: Types, models, trees & state\n---\n\n<div id=\"codefund\"></div>\n\n### tree = type + state\n\nEach **node**"
  },
  {
    "path": "docs/concepts/views.md",
    "chars": 2215,
    "preview": "---\nid: views\ntitle: Derived values\n---\n\n<div id=\"codefund\"></div>\n\n<details>\n    <summary style=\"color: white; backgrou"
  },
  {
    "path": "docs/concepts/volatiles.md",
    "chars": 6765,
    "preview": "---\nid: volatiles\ntitle: Volatile state\n---\n\n<div id=\"codefund\"></div>\n\n<details>\n    <summary style=\"color: white; back"
  },
  {
    "path": "docs/intro/examples.md",
    "chars": 726,
    "preview": "---\nid: examples\ntitle: Examples\n---\n\n<div id=\"codefund\"></div>\n\n- [Bookshop](https://github.com/coolsoftwaretyler/mst-e"
  },
  {
    "path": "docs/intro/getting-started.md",
    "chars": 26787,
    "preview": "---\nid: getting-started\ntitle: Getting Started Tutorial\n---\n\n<div id=\"codefund\"></div>\n\nThis tutorial will introduce you"
  },
  {
    "path": "docs/intro/installation.md",
    "chars": 1066,
    "preview": "---\nid: installation\ntitle: Installation\n---\n\n<div id=\"codefund\"></div>\n\n-   NPM: `npm install mobx mobx-state-tree --sa"
  },
  {
    "path": "docs/intro/philosophy.md",
    "chars": 6839,
    "preview": "---\nid: philosophy\ntitle: Overview & Philosophy\n---\n\n<div id=\"codefund\"></div>\n\n`mobx-state-tree` (also known as \"MST\") "
  },
  {
    "path": "docs/intro/welcome.md",
    "chars": 4684,
    "preview": "---\nid: welcome\ntitle: Welcome to MobX-State-Tree!\n---\n\n<div id=\"codefund\"></div>\n\n**_Full-featured reactive state manag"
  },
  {
    "path": "docs/overview/hooks.md",
    "chars": 13951,
    "preview": "---\nid: hooks\ntitle: Lifecycle hooks overview\n---\n\n<div id=\"codefund\"></div>\n\n<details>\n    <summary style=\"color: white"
  },
  {
    "path": "docs/overview/types.md",
    "chars": 8050,
    "preview": "---\nid: types\ntitle: Types overview\n---\n\n<div id=\"codefund\"></div>\n\n<details>\n    <summary style=\"color: white; backgrou"
  },
  {
    "path": "docs/overview/utilties.md",
    "chars": 27491,
    "preview": "---\nid: api\ntitle: API overview\n---\n\n<div id=\"codefund\"></div>\n\nSee the [TypeDocs](/API/) for full details and typings.\n"
  },
  {
    "path": "docs/recipes/auto-generated-property-setter-actions.md",
    "chars": 4286,
    "preview": "---\nid: auto-generated-property-setter-actions\ntitle: Auto-Generated Property Setter Actions\n---\n\nThis recipe was [origi"
  },
  {
    "path": "docs/recipes/mst-query.md",
    "chars": 9752,
    "preview": "---\nid: mst-query\ntitle: Manage Asynchronous Data with mst-query \n---\n\nFind the `mst-query` library on GitHub: https://g"
  },
  {
    "path": "docs/recipes/pre-built-form-types-with-mst-form-type.md",
    "chars": 19931,
    "preview": "---\nid: pre-built-form-types-with-mst-form-type\ntitle: Pre-built Form Types with MST Form Type\n---\n\nFind the `mst-form-t"
  },
  {
    "path": "docs/tips/circular-deps.md",
    "chars": 1101,
    "preview": "---\nid: circular-deps\nsidebar_label: Circular dependencies\ntitle: Handle circular dependencies between files and types u"
  },
  {
    "path": "docs/tips/faq.md",
    "chars": 3756,
    "preview": "---\nid: faq\ntitle: Frequently Asked Questions\n---\n\n<div id=\"codefund\"></div>\n\n### Should all state of my app be stored i"
  },
  {
    "path": "docs/tips/inheritance.md",
    "chars": 2371,
    "preview": "---\nid: inheritance\nsidebar_label: Simulating inheritance\ntitle: Simulate inheritance by using type composition\n---\n\n<di"
  },
  {
    "path": "docs/tips/more-tips.md",
    "chars": 2994,
    "preview": "---\nid: more-tips\ntitle: Miscellaneous Tips\n---\n\n<div id=\"codefund\"></div>\n\n### Generate MST models from JSON\n\nThe follo"
  },
  {
    "path": "docs/tips/resources.md",
    "chars": 4274,
    "preview": "---\nid: resources\ntitle: Talks & Blogs\n---\n\n<div id=\"codefund\"></div>\n\n## Official resources\n\n-   Introduction blog post"
  },
  {
    "path": "docs/tips/snapshots-as-values.md",
    "chars": 3196,
    "preview": "---\nid: snapshots-as-values\ntitle: Using snapshots as values\n---\n\n<div id=\"codefund\"></div>\n\nEverywhere where you can mo"
  },
  {
    "path": "docs/tips/typescript.md",
    "chars": 6584,
    "preview": "---\nid: typescript\ntitle: TypeScript and MST\n---\n\n<div id=\"codefund\"></div>\n\nTypeScript support is best-effort as not al"
  },
  {
    "path": "jest.config.js",
    "chars": 321,
    "preview": "module.exports = {\n  displayName: \"test\",\n  testEnvironment: \"node\",\n  transform: {\n    \"^.+\\\\.tsx?$\": \"ts-jest\"\n  },\n  "
  },
  {
    "path": "package.json",
    "chars": 4257,
    "preview": "{\n    \"name\": \"mobx-state-tree\",\n    \"version\": \"7.0.2\",\n    \"description\": \"Opinionated, transactional, MobX powered st"
  },
  {
    "path": "rollup.config.js",
    "chars": 1327,
    "preview": "import * as path from \"path\"\nimport filesize from \"rollup-plugin-filesize\"\nimport resolve from \"rollup-plugin-node-resol"
  },
  {
    "path": "scripts/fix-docs-source-links.js",
    "chars": 2916,
    "preview": "/**\n * Rewrites GitHub source links in generated API docs:\n * 1. Point to the canonical mobxjs/mobx-state-tree repo (so "
  },
  {
    "path": "scripts/generate-compose-type.js",
    "chars": 1161,
    "preview": "const { getDeclaration } = require(\"./generate-shared\")\n\nlet str = `// generated with ${__filename}\\n`\n\nconst minArgs = "
  },
  {
    "path": "scripts/generate-shared.js",
    "chars": 1446,
    "preview": "const alfa = \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"\n\nfunction getTemplateVar(templateVar, argNumber) {\n  return `${templateVar}${a"
  },
  {
    "path": "src/core/action.ts",
    "chars": 9176,
    "preview": "import { action as mobxAction } from \"mobx\"\nimport {\n    getStateTreeNode,\n    MstError,\n    argsToArray,\n    IDisposer,"
  },
  {
    "path": "src/core/actionContext.ts",
    "chars": 2183,
    "preview": "import { IAnyStateTreeNode, IMiddlewareEvent } from \"../internal\"\nimport { getCurrentActionContext } from \"./action\"\n\nex"
  },
  {
    "path": "src/core/flow.ts",
    "chars": 6508,
    "preview": "import { argsToArray, MstError, setImmediateWithFallback } from \"../utils\"\nimport {\n    FunctionWithFlag,\n    getCurrent"
  },
  {
    "path": "src/core/json-patch.ts",
    "chars": 3875,
    "preview": "import { MstError, stringStartsWith } from \"../internal\"\n\n/**\n * https://tools.ietf.org/html/rfc6902\n * http://jsonpatch"
  },
  {
    "path": "src/core/mst-operations.ts",
    "chars": 30735,
    "preview": "import { isComputedProp, isObservableProp } from \"mobx\"\nimport {\n    IAnyStateTreeNode,\n    IType,\n    IAnyModelType,\n  "
  },
  {
    "path": "src/core/node/BaseNode.ts",
    "chars": 5687,
    "preview": "import {\n    AnyObjectNode,\n    NodeLifeCycle,\n    Hook,\n    escapeJsonPath,\n    EventHandlers,\n    IAnyType,\n    IDispo"
  },
  {
    "path": "src/core/node/Hook.ts",
    "chars": 465,
    "preview": "/**\n * @hidden\n */\nexport enum Hook {\n    afterCreate = \"afterCreate\",\n    afterAttach = \"afterAttach\",\n    afterCreatio"
  },
  {
    "path": "src/core/node/create-node.ts",
    "chars": 1653,
    "preview": "import {\n    MstError,\n    ObjectNode,\n    ScalarNode,\n    AnyNode,\n    getStateTreeNodeSafe,\n    AnyObjectNode,\n    Com"
  },
  {
    "path": "src/core/node/identifier-cache.ts",
    "chars": 4766,
    "preview": "import { IObservableArray, values, observable, entries } from \"mobx\"\nimport { MstError, ObjectNode, mobxShallow, AnyObje"
  },
  {
    "path": "src/core/node/livelinessChecking.ts",
    "chars": 1501,
    "preview": "/**\n * Defines what MST should do when running into reads / writes to objects that have died.\n * - `\"warn\"`: Print a war"
  },
  {
    "path": "src/core/node/node-utils.ts",
    "chars": 5701,
    "preview": "import {\n    MstError,\n    ObjectNode,\n    splitJsonPath,\n    joinJsonPath,\n    ScalarNode,\n    IChildNodesMap,\n    EMPT"
  },
  {
    "path": "src/core/node/object-node.ts",
    "chars": 24784,
    "preview": "// noinspection ES6UnusedImports\nimport { action, computed, IComputedValue, reaction, _allowStateChangesInsideComputed }"
  },
  {
    "path": "src/core/node/scalar-node.ts",
    "chars": 3462,
    "preview": "import {\n    MstError,\n    freeze,\n    NodeLifeCycle,\n    Hook,\n    BaseNode,\n    AnyObjectNode,\n    SimpleType,\n    dev"
  },
  {
    "path": "src/core/process.ts",
    "chars": 3457,
    "preview": "import { deprecated, flow, createFlowSpawner } from \"../internal\"\n\n// based on: https://github.com/mobxjs/mobx-utils/blo"
  },
  {
    "path": "src/core/type/type-checker.ts",
    "chars": 5374,
    "preview": "import {\n    MstError,\n    EMPTY_ARRAY,\n    isPrimitive,\n    getStateTreeNode,\n    isStateTreeNode,\n    isPrimitiveType,"
  },
  {
    "path": "src/core/type/type.ts",
    "chars": 15572,
    "preview": "import { action } from \"mobx\"\n\nimport {\n    MstError,\n    isMutable,\n    isStateTreeNode,\n    getStateTreeNode,\n    IVal"
  },
  {
    "path": "src/index.ts",
    "chars": 3795,
    "preview": "// tslint:disable-next-line:no_unused-variable\nimport { IObservableArray, ObservableMap } from \"mobx\"\n\n/* all code is in"
  },
  {
    "path": "src/internal.ts",
    "chars": 1749,
    "preview": "/*\n * All imports / exports should be proxied through this file.\n * Why? It gives us full control over the module load o"
  },
  {
    "path": "src/middlewares/create-action-tracking-middleware.ts",
    "chars": 3684,
    "preview": "import { IMiddlewareEvent, IMiddlewareHandler } from \"../internal\"\n\nconst runningActions = new Map<number, { async: bool"
  },
  {
    "path": "src/middlewares/createActionTrackingMiddleware2.ts",
    "chars": 4960,
    "preview": "import { IMiddlewareEvent, IMiddlewareHandler, IActionContext } from \"../internal\"\n\nexport interface IActionTrackingMidd"
  },
  {
    "path": "src/middlewares/on-action.ts",
    "chars": 8745,
    "preview": "import { runInAction } from \"mobx\"\n\nimport {\n    getStateTreeNode,\n    isStateTreeNode,\n    addMiddleware,\n    tryResolv"
  },
  {
    "path": "src/types/complex-types/array.ts",
    "chars": 17160,
    "preview": "import {\n    _getAdministration,\n    action,\n    IArrayDidChange,\n    IArrayWillChange,\n    IArrayWillSplice,\n    interc"
  },
  {
    "path": "src/types/complex-types/map.ts",
    "chars": 17079,
    "preview": "import {\n    _interceptReads,\n    action,\n    IInterceptor,\n    IKeyValueMap,\n    IMapDidChange,\n    IMapWillChange,\n   "
  },
  {
    "path": "src/types/complex-types/model.ts",
    "chars": 41622,
    "preview": "import {\n    IObjectDidChange,\n    IObjectWillChange,\n    _getAdministration,\n    _interceptReads,\n    action,\n    compu"
  },
  {
    "path": "src/types/index.ts",
    "chars": 966,
    "preview": "// we import the types to re-export them inside types.\nimport {\n    enumeration,\n    model,\n    compose,\n    custom,\n   "
  },
  {
    "path": "src/types/primitives.ts",
    "chars": 7225,
    "preview": "import {\n    SimpleType,\n    isPrimitive,\n    MstError,\n    identity,\n    createScalarNode,\n    ISimpleType,\n    IType,\n"
  },
  {
    "path": "src/types/utility-types/custom.ts",
    "chars": 4644,
    "preview": "import {\n    createScalarNode,\n    SimpleType,\n    IType,\n    TypeFlags,\n    IValidationContext,\n    IValidationResult,\n"
  },
  {
    "path": "src/types/utility-types/enumeration.ts",
    "chars": 1955,
    "preview": "import { ISimpleType, union, literal, assertIsString, devMode } from \"../../internal\"\n\n/** @hidden */\nexport type UnionS"
  },
  {
    "path": "src/types/utility-types/frozen.ts",
    "chars": 3693,
    "preview": "import {\n    isSerializable,\n    deepFreeze,\n    createScalarNode,\n    IValidationContext,\n    IValidationResult,\n    ty"
  },
  {
    "path": "src/types/utility-types/identifier.ts",
    "chars": 4400,
    "preview": "import {\n    MstError,\n    createScalarNode,\n    SimpleType,\n    TypeFlags,\n    isType,\n    IValidationContext,\n    IVal"
  },
  {
    "path": "src/types/utility-types/late.ts",
    "chars": 4582,
    "preview": "import {\n    MstError,\n    BaseType,\n    IValidationContext,\n    IValidationResult,\n    TypeFlags,\n    isType,\n    IAnyT"
  },
  {
    "path": "src/types/utility-types/lazy.ts",
    "chars": 3647,
    "preview": "import { action, IObservableArray, observable, when } from \"mobx\"\nimport { AnyNode } from \"../../core/node/BaseNode\"\nimp"
  },
  {
    "path": "src/types/utility-types/literal.ts",
    "chars": 2200,
    "preview": "import {\n    isPrimitive,\n    createScalarNode,\n    ISimpleType,\n    TypeFlags,\n    IValidationContext,\n    IValidationR"
  },
  {
    "path": "src/types/utility-types/maybe.ts",
    "chars": 1273,
    "preview": "import {\n    union,\n    optional,\n    IType,\n    undefinedType,\n    nullType,\n    IAnyType,\n    assertIsType\n} from \"../"
  },
  {
    "path": "src/types/utility-types/optional.ts",
    "chars": 8268,
    "preview": "import {\n    isStateTreeNode,\n    IType,\n    TypeFlags,\n    isType,\n    IValidationContext,\n    IValidationResult,\n    t"
  },
  {
    "path": "src/types/utility-types/reference.ts",
    "chars": 20309,
    "preview": "import {\n    getStateTreeNode,\n    isStateTreeNode,\n    createScalarNode,\n    IType,\n    TypeFlags,\n    IValidationConte"
  },
  {
    "path": "src/types/utility-types/refinement.ts",
    "chars": 3546,
    "preview": "import {\n    isStateTreeNode,\n    getStateTreeNode,\n    IValidationContext,\n    IValidationResult,\n    typeCheckSuccess,"
  },
  {
    "path": "src/types/utility-types/snapshotProcessor.ts",
    "chars": 8785,
    "preview": "import {\n    IType,\n    IAnyType,\n    BaseType,\n    isStateTreeNode,\n    IValidationContext,\n    IValidationResult,\n    "
  },
  {
    "path": "src/types/utility-types/union.ts",
    "chars": 6622,
    "preview": "import {\n    IValidationContext,\n    IValidationResult,\n    typeCheckSuccess,\n    typeCheckFailure,\n    flattenTypeError"
  },
  {
    "path": "src/utils.ts",
    "chars": 10721,
    "preview": "import {\n    isObservableArray,\n    isObservableObject,\n    _getGlobalState,\n    defineProperty as mobxDefineProperty\n} "
  },
  {
    "path": "test-results/.gitkeep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "tsconfig.json",
    "chars": 687,
    "preview": "{\n  \"compilerOptions\": {\n    \"outDir\": \"lib/\",\n    \"target\": \"es5\",\n    \"sourceMap\": false,\n    \"declaration\": true,\n   "
  },
  {
    "path": "tslint.json",
    "chars": 851,
    "preview": "{\n    \"extends\": [\"tslint-config-prettier\"],\n    \"rules\": {\n        \"class-name\": true,\n        \"comment-format\": [true,"
  },
  {
    "path": "typedocconfig.js",
    "chars": 546,
    "preview": "module.exports = {\n    src: [\"src/index.ts\"],\n    module: \"commonjs\",\n    excludeNotExported: true,\n    excludePrivate: "
  },
  {
    "path": "website/core/Footer.js",
    "chars": 4214,
    "preview": "/**\n * Copyright (c) 2017-present, Facebook, Inc.\n *\n * This source code is licensed under the MIT license found in the\n"
  },
  {
    "path": "website/i18n/en.json",
    "chars": 7909,
    "preview": "{\n  \"_comment\": \"This file is auto-generated by write-translations.js\",\n  \"localized-strings\": {\n    \"next\": \"Next\",\n   "
  },
  {
    "path": "website/package.json",
    "chars": 376,
    "preview": "{\n  \"scripts\": {\n    \"examples\": \"docusaurus-examples\",\n    \"start\": \"docusaurus-start\",\n    \"build\": \"docusaurus-build\""
  }
]

// ... and 6 more files (download for full content)

About this extraction

This page contains the full source code of the mobxjs/mobx-state-tree GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 206 files (1.4 MB), approximately 367.6k tokens, and a symbol index with 1111 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!