[
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*]\nindent_style = tab\nend_of_line = lf\ncharset = utf-8\ntrim_trailing_whitespace = true\ninsert_final_newline = true\n\n[*.yml]\nindent_style = space\nindent_size = 2\n"
  },
  {
    "path": ".gitattributes",
    "content": "* text=auto eol=lf\n"
  },
  {
    "path": ".github/workflows/main.yml",
    "content": "name: CI\non:\n  - push\n  - pull_request\njobs:\n  test:\n    name: Node.js ${{ matrix.node-version }}\n    runs-on: ubuntu-latest\n    strategy:\n      fail-fast: false\n      matrix:\n        node-version:\n          - 16\n          - 14\n          - 12\n    steps:\n      - uses: actions/checkout@v2\n      - uses: actions/setup-node@v2\n        with:\n          node-version: ${{ matrix.node-version }}\n      - run: npm install\n      - run: npm test\n"
  },
  {
    "path": ".gitignore",
    "content": "node_modules\nyarn.lock\n"
  },
  {
    "path": ".npmrc",
    "content": "package-lock=false\n"
  },
  {
    "path": "browser-env.js",
    "content": "import browserEnv from 'browser-env';\n\nbrowserEnv();\n"
  },
  {
    "path": "index.d.ts",
    "content": "import {Container} from 'unstated';\n\n/**\nWhen enabled, it exposes a global object `UNSTATED` which you can use in DevTools to explore the containers and their state.\n\nIn the root of your app, import `unstated-debug`:\n\n@example\n```\nimport React from 'react';\nimport {render} from 'react-dom';\nimport {Provider} from 'unstated';\nimport UNSTATED from 'unstated-debug';\nimport App from './components/App.js';\n\nUNSTATED.logStateChanges = false;\n\nrender(\n\t<Provider>\n\t\t<App/>\n\t</Provider>,\n\tdocument.querySelector('#root')\n);\n```\n*/\ndeclare const UNSTATED: {\n\t/**\n\tWhether the debugger should be enabled or not.\n\n\t@default true\n\t*/\n\tisEnabled: boolean;\n\n\t/**\n\tWhether state changes should be logged to the console.\n\n\t@default true\n\t*/\n\tlogStateChanges: boolean;\n\n\t/**\n\tWhether logs should be collapsed.\n\n\t@default false\n\t*/\n\tisCollapsed: boolean;\n\n\t/**\n\tYour containers.\n\t*/\n\tcontainers: Record<string, Container<Record<string, unknown>>>;\n\n\t/**\n\tAll of the state values.\n\t*/\n\tstates: Record<string, Record<string, unknown>>;\n\n\t/**\n\tLogs the current state of your containers.\n\t*/\n\tlogState: () => void;\n};\n\nexport default UNSTATED;\n"
  },
  {
    "path": "index.js",
    "content": "import {detailedDiff} from 'deep-object-diff';\nimport {__SUPER_SECRET_CONTAINER_DEBUG_HOOK__} from 'unstated';\n\nconst UNSTATED = {\n\tisEnabled: true,\n\tisCollapsed: false,\n\tlogStateChanges: true,\n\tcontainers: {},\n\tget states() {\n\t\treturn Object.fromEntries(\n\t\t\tObject.entries(this.containers).map(([key, value]) => [key, value.state])\n\t\t);\n\t},\n\tlogState() {\n\t\tfor (const [key, value] of Object.entries(this.containers)) {\n\t\t\tconsole.log(`%c${key}\\n`, 'font-weight:bold', value.state);\n\t\t}\n\t}\n};\n\n__SUPER_SECRET_CONTAINER_DEBUG_HOOK__(container => {\n\tif (!UNSTATED.isEnabled) {\n\t\treturn;\n\t}\n\n\tconst {name} = container.constructor;\n\n\tUNSTATED.containers[name] = container;\n\n\tlet previousState = container.state;\n\n\tcontainer.subscribe(() => {\n\t\tif (!(UNSTATED.isEnabled && UNSTATED.logStateChanges)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst {state} = container;\n\t\tconst diff = detailedDiff(previousState, state);\n\n\t\tconst group = UNSTATED.isCollapsed ? console.groupCollapsed : console.group;\n\t\tgroup(name);\n\n\t\tconst hasChanges = object => Object.keys(object).length > 0;\n\n\t\tif (hasChanges(diff.added)) {\n\t\t\tconsole.log('Added\\n', diff.added);\n\t\t}\n\n\t\tif (hasChanges(diff.updated)) {\n\t\t\tconsole.log('Updated\\n', diff.updated);\n\t\t}\n\n\t\tif (hasChanges(diff.deleted)) {\n\t\t\tconsole.log('Deleted\\n', diff.deleted);\n\t\t}\n\n\t\tconsole.log('New state\\n', state);\n\t\tconsole.log('Old state\\n', previousState);\n\n\t\tconsole.groupEnd(name);\n\n\t\tpreviousState = state;\n\t});\n});\n\nif (typeof window !== 'undefined') {\n\twindow.UNSTATED = UNSTATED;\n}\n\nexport default UNSTATED;\n"
  },
  {
    "path": "index.test-d.ts",
    "content": "import {expectType} from 'tsd';\nimport {Container} from 'unstated';\nimport UNSTATED from './index.js';\n\nexpectType<boolean>(UNSTATED.isEnabled);\nexpectType<boolean>(UNSTATED.logStateChanges);\n\nexpectType<Record<string, Container<Record<string, unknown>>>>(UNSTATED.containers);\n\nexpectType<() => void>(UNSTATED.logState);\n\nexpectType<Record<string, Record<string, unknown>>>(\n\tUNSTATED.states\n);\n"
  },
  {
    "path": "license",
    "content": "MIT License\n\nCopyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)\n\nPermission 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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.\n"
  },
  {
    "path": "package.json",
    "content": "{\n\t\"name\": \"unstated-debug\",\n\t\"version\": \"1.0.0\",\n\t\"description\": \"Debug your Unstated containers with ease\",\n\t\"license\": \"MIT\",\n\t\"repository\": \"sindresorhus/unstated-debug\",\n\t\"funding\": \"https://github.com/sponsors/sindresorhus\",\n\t\"author\": {\n\t\t\"name\": \"Sindre Sorhus\",\n\t\t\"email\": \"sindresorhus@gmail.com\",\n\t\t\"url\": \"https://sindresorhus.com\"\n\t},\n\t\"type\": \"module\",\n\t\"exports\": \"./index.js\",\n\t\"engines\": {\n\t\t\"node\": \">=12\"\n\t},\n\t\"scripts\": {\n\t\t\"test\": \"xo && ava && tsd\"\n\t},\n\t\"files\": [\n\t\t\"index.js\",\n\t\t\"index.d.ts\"\n\t],\n\t\"keywords\": [\n\t\t\"unstated\",\n\t\t\"debug\",\n\t\t\"container\",\n\t\t\"containers\",\n\t\t\"react\",\n\t\t\"state\",\n\t\t\"component\",\n\t\t\"debugging\",\n\t\t\"debuggable\",\n\t\t\"inspect\",\n\t\t\"devtools\"\n\t],\n\t\"dependencies\": {\n\t\t\"deep-object-diff\": \"^1.1.0\"\n\t},\n\t\"devDependencies\": {\n\t\t\"@types/react\": \"^17.0.4\",\n\t\t\"ava\": \"^3.15.0\",\n\t\t\"browser-env\": \"^3.3.0\",\n\t\t\"react\": \"^16.0.0\",\n\t\t\"tsd\": \"^0.14.0\",\n\t\t\"unstated\": \"^2.1.1\",\n\t\t\"xo\": \"^0.39.1\"\n\t},\n\t\"peerDependencies\": {\n\t\t\"unstated\": \"^2.1.1\"\n\t},\n\t\"xo\": {\n\t\t\"envs\": [\n\t\t\t\"node\",\n\t\t\t\"browser\"\n\t\t]\n\t},\n\t\"ava\": {\n\t\t\"require\": [\n\t\t\t\"./browser-env\"\n\t\t]\n\t}\n}\n"
  },
  {
    "path": "readme.md",
    "content": "# unstated-debug\n\n> Debug your [Unstated](https://github.com/jamiebuilds/unstated) containers with ease\n\n<br>\n<img src=\"screenshot.png\" width=\"1145\">\n\n## Install\n\n```\n$ npm install unstated-debug\n```\n\n## Setup\n\nIn the root of your app, import `unstated-debug`:\n\n```js\nimport React from 'react';\nimport {render} from 'react-dom';\nimport {Provider} from 'unstated';\nimport UNSTATED from 'unstated-debug';\nimport App from './components/App.js';\n\nUNSTATED.logStateChanges = false;\n\nrender(\n\t<Provider>\n\t\t<App/>\n\t</Provider>,\n\tdocument.querySelector('#root')\n);\n```\n\n## Usage\n\nWhen enabled, it exposes a global object `UNSTATED` which you can use in DevTools to explore the containers and their state.\n\n<img src=\"screenshot-explore.png\" width=\"400\">\n\nThe object contains the following properties:\n\n- `isEnabled` - Same as the below option, but you can change it after init.\n- `logStateChanges` - Same as the below option, but you can change it after init.\n- `isCollapsed` - Collapse logs. (Default: false)\n- `containers` - Your containers.\n- `states` - The state objects of your containers.\n- `logState()` - Logs the current state of your containers.\n\n## API\n\n### UNSTATED\n\n##### isEnabled\n\nType: `boolean`\\\nDefault: `true`\n\nToggle debugging.\n\nFor example, if you use this in an Electron app, you could pass it [`is.development`](https://github.com/sindresorhus/electron-util#is) to ensure debugging is disabled in production.\n\n##### logStateChanges\n\nType: `boolean`\\\nDefault: `true`\n\nLogs a diff for each state change to the containers. This gives you a live insight into state changes in your app.\n\n<img src=\"screenshot-diff.png\" width=\"400\">\n"
  },
  {
    "path": "test.js",
    "content": "import test from 'ava';\nimport {Container} from 'unstated';\nimport UNSTATED from './index.js';\n\nclass FixtureContainer extends Container {\n\tconstructor() {\n\t\tsuper();\n\n\t\tthis.state = {\n\t\t\tfoo: true\n\t\t};\n\t}\n}\n\nconst container = new FixtureContainer();\n\ntest('main', t => {\n\tt.true(container.state.foo);\n});\n\ntest('exposes window global', t => {\n\tt.is(UNSTATED, window.UNSTATED);\n\tt.is(typeof window.UNSTATED, 'object');\n\tt.true(window.UNSTATED.containers.FixtureContainer.state.foo);\n});\n"
  }
]