{"_id":"ibiza","_rev":"46-dac634a9ffd828d4d1beab9d33003304","name":"ibiza","dist-tags":{"latest":"1.4.0","beta":"1.3.0-0","true":"1.5.1","alpha":"2.0.0-alpha.15"},"versions":{"1.0.0-beta.1":{"name":"ibiza","author":{"name":"Joel Moss"},"version":"1.0.0-beta.1","description":"React State Management for Party Animals","license":"MIT","homepage":"https://github.com/joelmoss/ibiza","repository":{"type":"git","url":"https://github.com/joelmoss/ibiza.git"},"bugs":{"url":"https://github.com/joelmoss/ibiza/issues"},"keywords":["react","state","proxy"],"browser":"index.js","type":"module","scripts":{"test":"jest"},"prettier":{"trailingComma":"none","printWidth":100,"semi":false,"singleQuote":true,"arrowParens":"avoid"},"peerDependencies":{"react":">=16","react-dom":">=16"},"devDependencies":{"@babel/core":"^7.16.0","@babel/preset-env":"^7.16.4","@babel/preset-react":"^7.16.0","@testing-library/jest-dom":"^5.15.0","@testing-library/react":"^12.1.2","@testing-library/react-hooks":"^7.0.2","babel-jest":"^27.3.1","cross-fetch":"^3.1.4","fetch-mock-jest":"^1.5.1","jest":"^27.3.1","msw":"^0.35.0","react":"^17.0.2","react-dom":"^17.0.2"},"dependencies":{"fast-equals":"^2.0.3","micro-memoize":"^4.0.9"},"_id":"ibiza@1.0.0-beta.1","dist":{"shasum":"3327e630110eca1d236b0b564b539b244cbea0c1","integrity":"sha512-OKEz4WW4xqY81qXVqB6lqhax/D5I0yKcIT2qKe2bSjrA0t09WPcyRm98MgpNlvumg2SpDJpq8qR9Z6P9OOqlGA==","tarball":"https://registry.npmjs.org/ibiza/-/ibiza-1.0.0-beta.1.tgz","fileCount":19,"unpackedSize":119940,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhlYiUCRA9TVsSAnZWagAAaqEP/3sA776/8+mUpB+LQ0Ur\nVu5XRu2mAeLU4tQtRkFN1wyRHkqeeqlvckZpfrvOPbUpXtaTjV6aIG8rGIoy\nNiH0WVosu+1JeHd6TIj0lZXNYIBNQ8iPPIlZDlQn16R8NyzBLNI8j7XuRETn\nVFbRjK9oPLuax/vrrHI8k3qiRBCgg1hWSC3shIp+Hz5Ibu5Aws95KCGfkjJf\nsanFpmyUvDXIO/uDL87Q3IDG13//rA4ndMlQR/ZM2U/WIOSQ/fawzPnuSqUl\ntqE7zj6an8UzVe0Ir0Jr/rodbvmvW54WgLTxbj6sMh5+YNgBtdkYyjbsLml3\nJiC0jFLI0zEY1xpRIUVtoAlBvk5nrkNW5Gkj9k2z8xWl3k8aOSBzjt+V5kCP\n+p8GvF7yhGtxvNvfA+wqyXt2FsfLKobDv/0joMyycfFVE9CRJaqsXuxnVm8B\nO2mJ+dawkFtDJo21OGS5TN1phExwutTQUTuky3p+o/WB6V8CWkmtk0Dzz1PH\nQhhmzGKxu1Xs7tACTpWk8THEt9JRih+bsrKejklP8GRxzY9YT72bHW1wdClC\nZX7E4CyUhFO4QS3uUoFog5lQkj91nOodVhrnSf+8T9TzHnBzUABHQmoGvoNS\nWy2sMubrQaoz5d518Wl4gKifjj5vpfgrXSnhiuB/ozhvlK57scXoe3tQ8QjK\nkIwV\r\n=Cd9E\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD1STOkO5b6sI5rMFdx65gHNfML41K6gOFGIhysjcphagIhAOobuw+ijOXcbOTTnmAEGyuB2U/7ZPLyzNm8RgHpJ2vq"}]},"_npmUser":{"name":"joelmoss","email":"joel@developwithstyle.com"},"directories":{},"maintainers":[{"name":"joelmoss","email":"joel@developwithstyle.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ibiza_1.0.0-beta.1_1637189780048_0.6986167299704631"},"_hasShrinkwrap":false},"1.0.0-beta.2":{"name":"ibiza","author":{"name":"Joel Moss"},"version":"1.0.0-beta.2","description":"React State Management for Party Animals","license":"MIT","homepage":"https://github.com/joelmoss/ibiza","repository":{"type":"git","url":"https://github.com/joelmoss/ibiza.git"},"bugs":{"url":"https://github.com/joelmoss/ibiza/issues"},"keywords":["react","state","proxy"],"source":"index.js","main":"dist/main.js","module":"dist/module.js","sideEffects":false,"scripts":{"test":"jest","build":"parcel build","size":"size-limit","prepack":"parcel build"},"size-limit":[{"name":"useIbiza","path":"index.js","import":"{ useIbiza }"},{"name":"store","path":"index.js","import":"{ store }"},{"name":"createModel","path":"index.js","import":"{ createModel }"}],"prettier":{"trailingComma":"none","printWidth":100,"semi":false,"singleQuote":true,"arrowParens":"avoid"},"peerDependencies":{"react":">=16"},"devDependencies":{"@babel/core":"^7.16.0","@babel/preset-env":"^7.16.4","@babel/preset-react":"^7.16.0","@size-limit/preset-small-lib":"^7.0.0","@testing-library/jest-dom":"^5.15.0","@testing-library/react":"^12.1.2","@testing-library/react-hooks":"^7.0.2","babel-jest":"^27.3.1","cross-fetch":"^3.1.4","fetch-mock-jest":"^1.5.1","jest":"^27.3.1","msw":"^0.35.0","parcel":"^2.0.1","react":"^17.0.2","react-dom":"^17.0.2","size-limit":"^7.0.0"},"dependencies":{"fast-equals":"^2.0.3","lodash":"^4.17.21","micro-memoize":"^4.0.9"},"readmeFilename":"README.md","readme":"# Ibiza - React State Management for Party Animals\n\nIbiza gets out of your way and simply lets you read and write state as you would with regular\nJavascript assignment. It maintains a global state object and is smart enough to know when to\nrerender your components based on state usage and modification.\n\n## How It Works ✨\n\nA component calls the `useIbiza` React hook, which returns the store state as a JS Proxy object.\nThis Proxy records when a state property is accessed or \"used\". Then when that property is mutated,\nthe component is rerendered.\n\nThis means that you can mutate your state in any way, but your component will only rerender if you\nmutate state that you have used.\n\nState can be mutated from anywhere - not just from within a component.\n\nThe following component will rerender when the button is clicked, because `name` has changed.\n\n```jsx\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n      <button onClick={() => void (state.name = 'Joel')}></button>\n    </div>\n  )\n}\n```\n\nThe following component will not rerender when the button is clicked, because even though `age` has\nbeen mutated, it is not actually being used within the component.\n\n```jsx\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n      <button onClick={() => void (state.age = 44)}></button>\n    </div>\n  )\n}\n```\n\n### Initial State\n\nYou can pass some initial state to `useIbiza` which will be merged with existing state in the Ibiza\nstore.\n\n```jsx\nconst App = () => {\n  const state = useIbiza({ user: { name: 'Joel' } })\n\n  return <h1>Hello {state.name}</h1>\n}\n```\n\nThis is safe to include in the body of your component, as it will only be merged into the store on\nfirst render.\n\n### Slicing\n\nIbiza supports deeply nested objects, allowing you to design the shape of your state any way you\nlike. To help you work with such nested state, the `useIbiza` hook supports slicing.\n\nThe following example assumes you have an existing state object:\n\n```javascript\n{\n  user: {\n    name: 'Joel',\n    partner: {\n      name: 'Sam',\n    }\n  }\n}\n```\n\nPass a string to `useIbiza` to fetch a specific slice of state. The string should be the path to the\nobject that you want.\n\n```jsx\nconst App = () => {\n  const partner = useIbiza('user.partner')\n\n  return (\n    <div>\n      <h1>Hello {partner.name}</h1>\n      <button onClick={() => void (partner.name = 'Bob')}></button>\n    </div>\n  )\n}\n```\n\nNote that slicing is really only supported as a convenience, and will not generally help with\nperformance.\n\n### Models\n\nIbiza is at its most powerful when working with models. They provide reusability and flexibility.\n\nCreate a model using the `createModel` helper, where the first argument is the model name, and the\nsecond argument is the initial model state.\n\n```javascript\nexport default createModel('user', {\n  firstName: 'Joel',\n  lastName: 'Moss',\n  children: [{ firstName: 'Ash' }, { firstName: 'Elijah' }, { firstName: 'Eve' }]\n})\n```\n\n`createModel` returns a hook which you can use. You can now import your model anywhere:\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <div>\n      <h1>Hello {user.firstName}</h1>\n      <ul>\n        {user.children.map((child, i) => (\n          <li key={i}>{child.firstName}</li>\n        ))}\n      </ul>\n    </div>\n  )\n}\n```\n\n#### Initial State\n\nSometimes you want to be able to define your model with some initial state that could be provided\ndynamically. For example, from component props or some other parameters.\n\n`createModel` can accept a function as its second argument. This function will be called on\ninitialisation with two arguments; the current `state` and any `props` passed to it when its hook is\nfirst called.\n\n```javascript\nexport default createModel('user', (state, props) => ({\n  firstName: 'Joel',\n  lastName: 'Moss'\n  ...props\n}))\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = ({ yearOfBirth }) => {\n  const user = useModel({ yearOfBirth })\n\n  return (\n    <div>\n      <h1>\n        Hello {user.firstName}, you were born in {user.yearOfBirth}.\n      </h1>\n    </div>\n  )\n}\n```\n\n### Functions\n\nYou can use regular function in your model. They accept the current state as the first argument, and\n`this` will also be the current state (as long as you don't use hash rocket functions).\n\n```jsx\nconst App = () => {\n  const state = useIbiza({\n    count: 0,\n    increment: state => {\n      ++state.count\n    },\n    decrement() {\n      ++this.count\n    }\n  })\n\n  return (\n    <>\n      <h1>Count = {state.count}</h1>\n      <button onClick={state.increment}>Increment</button>\n      <button onClick={state.decrement}>Decrement</button>\n    </>\n  )\n}\n```\n\nWhen reading/writing state within a function, `this` responds to the state at the level where the\nfunction sits. This means that if the function is deeply nested, `this` will not include state lower\ndown.\n\nTo solve this, you can call `this.$model` to access your model, or `this.$root` to access the root\nof the state.\n\n```javascript\nuseIbiza({\n  deepstate: {\n    user: {\n      name: 'Joel',\n      partner: {\n        name: 'Sam',\n\n        get partner() {\n          // `this` refers to 'deepstate.user.partner'.\n          // `this.$model` refers to 'deepstate.user'.\n          // `this.$root` is the whole store state.\n          return this.$model.name\n        }\n      }\n    }\n  }\n})\n```\n\nFunctions accept any number of arguments just like regular functions do.\n\n```jsx\nconst App = () => {\n  const user = useIbiza({\n    children: [],\n    addChild(state, firstName, lastName) {\n      state.children.push({ firstName, lastName }) // or `this.children.push(...)`\n    }\n  })\n\n  return (\n    <>\n      <ul>\n        {user.children.map((child, i) => (\n          <li key={i}>\n            {child.firstName} {child.lastName}\n          </li>\n        ))}\n      </ul>\n      <button onClick={() => user.addChild('Ash', 'Moss')}></button>\n    </>\n  )\n}\n```\n\n### Getters and Setters\n\nIbiza supports Javascript getters and setters in your state and models.\n\n```javascript\nexport default createModel('user', {\n  firstName: 'Joel',\n  lastName: 'Moss',\n\n  get fullName() {\n    // You can read/write to your state via `this`.\n    return `${this.firstName} ${this.lastName}`\n  },\n\n  set fullName(value) {\n    const [firstName, lastName] = value.split(' ')\n\n    this.firstName = firstName\n    this.lastName = lastName\n  }\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <h1>Hello {user.fullName}</h1>\n      <button onClick={() => void (user.fullName = 'Bob Bones')}></button>\n    </>\n  )\n}\n```\n\n### Async Functions\n\nFunctions can be async and/or return Promises, and support React's Suspense by default.\n\n```javascript\nexport default createModel('user', {\n  name: 'Joel',\n\n  async doSomething() {\n    return await someAsyncAction()\n  }\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <h1>Hello {user.fullName}</h1>\n      <button onClick={user.doSomething}></button>\n    </>\n  )\n}\n```\n\n### URL Models\n\nBecause reading and writing to/from the server is so common, Ibiza has support to make this easy\nwith URL Models, similar to react-query. Simply use a valid and relative URL as you model name or\nslice.\n\nThe following will fetch the user from the server at `/user`, suspending the component while it does\nso. The data is fetched only when it does not exist in the store.\n\n```jsx\nconst App = () => {\n  const user = useIbiza('/user')\n\n  return <h1>Hello {user.name}</h1>\n}\n```\n\nYou can safely mutate your model, as all mutations will remain local.\n\nYou can write your model state back to the server. It the server responds with JSON, the model will\nbe updated with that response.\n\n```jsx\nconst App = () => {\n  const user = useIbiza('/user')\n\n  const renameUser = async () => {\n    await user.save({ body: { name: 'Bob' } })\n  }\n\n  return (\n    <>\n      <h1>Hello {user.name}</h1>\n      <button onClick={() => renameUser()}></button>\n    </>\n  )\n}\n```\n\nURL Models can also be defined with `createModel`:\n\n```javascript\nexport default createModel('/user')\n```\n\n`createModel` returns a hook which you can use. You can now import your model anywhere:\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return <h1>Hello {user.firstName}</h1>\n}\n```\n","_id":"ibiza@1.0.0-beta.2","dist":{"shasum":"29ff4107b6655b7e46eeffbdd2f0e5983d277325","integrity":"sha512-HWm/H1LEwfMzlEvy/phwNyo7cFvyyB4H2ZMyOk/PrOkDvLJZlJN39al0ww5xdRbDeuubLlLONBLyzlwrEM3EnQ==","tarball":"https://registry.npmjs.org/ibiza/-/ibiza-1.0.0-beta.2.tgz","fileCount":21,"unpackedSize":147598,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhlaboCRA9TVsSAnZWagAA2L4P/0cd5bF9P9CXSJNT0ouw\nJoaf3/IjzZbbI1tt1jXQMh5g6fQrrzME6an1uabC2CW6GO7Ye5ZHZmgWejef\nxoRujfo9tRuJkdnXoU/PYN4Sbc7MGcPQO5wYh8f+/WWljoXhbZzC8rgJaFsc\np0FfRLrc98jGZcHMQJXoE5UYC4HgiYLueJ1C29nKyHlvcWI6eA/tvrWkgBES\n9tT5nwy/AIr6zKKyeNz5YbyYw1VbjPA6sPKTN191H2mjzhXpQB+LQuhFOj+5\nPrz3OndflAxAaHEinycA/oJy48J+yiZchafazDmw3edkOoJOxYpNfP6YfQI8\nP1AfeeXFUK45D4ionr8cFzE+ljJ7wzCOHPvm/hg23Naniw7S/4MnUqHYp54e\nasnWkpQBlHwQGmeN0FrREHzFyw7lZyXDObrfKS0egOgRyp3X/rJ9POjjkYe0\nO134I97bKptIyAs2Ghn38fUdRhPPPWF7yMPMgbWoxjsrV8+PDKP15rW1zlO6\nC65Y5h1iijBgdAB/Zy2qKR2TPt6wRck3bzoC01Vx4B+Ep0XyiFnyMfeV/Fn+\nItsOLgo0gRfKAXm+B9EaBpeJsadXQG1ub2wC6jeuOfnVBgU0R5ynnblRyHT8\n8o6QqcgCBDtlAQfk9LDy+Lb+qXgUtbhXmvNFbDDwGBBix28yJ9jfLchDxABc\nSBM6\r\n=udeh\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICUOGQLQiq8h5scD4o1wGxD6iiAdEtR89+te5WUrWbEqAiEA40+R1mBbBnh7e1UKl7coXXwOoT4BeuH8VktTXxdv0CY="}]},"_npmUser":{"name":"joelmoss","email":"joel@developwithstyle.com"},"directories":{},"maintainers":[{"name":"joelmoss","email":"joel@developwithstyle.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ibiza_1.0.0-beta.2_1637197544276_0.2987414789150684"},"_hasShrinkwrap":false},"1.0.0-beta.3":{"name":"ibiza","author":{"name":"Joel Moss"},"version":"1.0.0-beta.3","description":"React State Management for Party Animals","license":"MIT","homepage":"https://github.com/joelmoss/ibiza","repository":{"type":"git","url":"https://github.com/joelmoss/ibiza.git"},"bugs":{"url":"https://github.com/joelmoss/ibiza/issues"},"keywords":["react","state","proxy"],"source":"index.js","browser":"dist/index.cjs","module":"dist/index.js","sideEffects":false,"scripts":{"test":"jest","build":"rollup -c","prepublishOnly":"npm run build","size":"size-limit"},"size-limit":[{"name":"useIbiza","path":"index.js","import":"{ useIbiza }"},{"name":"store","path":"index.js","import":"{ store }"},{"name":"createModel","path":"index.js","import":"{ createModel }"}],"prettier":{"trailingComma":"none","printWidth":100,"semi":false,"singleQuote":true,"arrowParens":"avoid"},"peerDependencies":{"react":">=16"},"devDependencies":{"@babel/core":"^7.16.0","@babel/plugin-transform-runtime":"^7.16.4","@babel/preset-env":"^7.16.4","@babel/preset-react":"^7.16.0","@rollup/plugin-babel":"^5.3.0","@rollup/plugin-node-resolve":"^13.0.6","@size-limit/preset-small-lib":"^7.0.0","@testing-library/jest-dom":"^5.15.0","@testing-library/react":"^12.1.2","@testing-library/react-hooks":"^7.0.2","babel-jest":"^27.3.1","babel-plugin-lodash":"^3.3.4","cross-fetch":"^3.1.4","fetch-mock-jest":"^1.5.1","jest":"^27.3.1","msw":"^0.35.0","parcel":"^2.0.1","react":"^17.0.2","react-dom":"^17.0.2","rollup":"^2.60.0","rollup-plugin-size":"^0.2.2","rollup-plugin-terser":"^7.0.2","size-limit":"^7.0.0"},"dependencies":{"fast-equals":"^2.0.3","lodash":"^4.17.21","micro-memoize":"^4.0.9"},"readmeFilename":"README.md","readme":"# Ibiza - React State Management for Party Animals\n\nIbiza gets out of your way and simply lets you read and write state as you would with regular\nJavascript assignment. It maintains a global state object and is smart enough to know when to\nrerender your components based on state usage and modification.\n\n## How It Works ✨\n\nA component calls the `useIbiza` React hook, which returns the store state as a JS Proxy object.\nThis Proxy records when a state property is accessed or \"used\". Then when that property is mutated,\nthe component is rerendered.\n\nThis means that you can mutate your state in any way, but your component will only rerender if you\nmutate state that you have used.\n\nState can be mutated from anywhere - not just from within a component.\n\nThe following component will rerender when the button is clicked, because `name` has changed.\n\n```jsx\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n      <button onClick={() => void (state.name = 'Joel')}></button>\n    </div>\n  )\n}\n```\n\nThe following component will not rerender when the button is clicked, because even though `age` has\nbeen mutated, it is not actually being used within the component.\n\n```jsx\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n      <button onClick={() => void (state.age = 44)}></button>\n    </div>\n  )\n}\n```\n\n### Initial State\n\nYou can pass some initial state to `useIbiza` which will be merged with existing state in the Ibiza\nstore.\n\n```jsx\nconst App = () => {\n  const state = useIbiza({ user: { name: 'Joel' } })\n\n  return <h1>Hello {state.name}</h1>\n}\n```\n\nThis is safe to include in the body of your component, as it will only be merged into the store on\nfirst render.\n\n### Slicing\n\nIbiza supports deeply nested objects, allowing you to design the shape of your state any way you\nlike. To help you work with such nested state, the `useIbiza` hook supports slicing.\n\nThe following example assumes you have an existing state object:\n\n```javascript\n{\n  user: {\n    name: 'Joel',\n    partner: {\n      name: 'Sam',\n    }\n  }\n}\n```\n\nPass a string to `useIbiza` to fetch a specific slice of state. The string should be the path to the\nobject that you want.\n\n```jsx\nconst App = () => {\n  const partner = useIbiza('user.partner')\n\n  return (\n    <div>\n      <h1>Hello {partner.name}</h1>\n      <button onClick={() => void (partner.name = 'Bob')}></button>\n    </div>\n  )\n}\n```\n\nNote that slicing is really only supported as a convenience, and will not generally help with\nperformance.\n\n### Models\n\nIbiza is at its most powerful when working with models. They provide reusability and flexibility.\n\nCreate a model using the `createModel` helper, where the first argument is the model name, and the\nsecond argument is the initial model state.\n\n```javascript\nexport default createModel('user', {\n  firstName: 'Joel',\n  lastName: 'Moss',\n  children: [{ firstName: 'Ash' }, { firstName: 'Elijah' }, { firstName: 'Eve' }]\n})\n```\n\n`createModel` returns a hook which you can use. You can now import your model anywhere:\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <div>\n      <h1>Hello {user.firstName}</h1>\n      <ul>\n        {user.children.map((child, i) => (\n          <li key={i}>{child.firstName}</li>\n        ))}\n      </ul>\n    </div>\n  )\n}\n```\n\n#### Initial State\n\nSometimes you want to be able to define your model with some initial state that could be provided\ndynamically. For example, from component props or some other parameters.\n\n`createModel` can accept a function as its second argument. This function will be called on\ninitialisation with two arguments; the current `state` and any `props` passed to it when its hook is\nfirst called.\n\n```javascript\nexport default createModel('user', (state, props) => ({\n  firstName: 'Joel',\n  lastName: 'Moss'\n  ...props\n}))\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = ({ yearOfBirth }) => {\n  const user = useModel({ yearOfBirth })\n\n  return (\n    <div>\n      <h1>\n        Hello {user.firstName}, you were born in {user.yearOfBirth}.\n      </h1>\n    </div>\n  )\n}\n```\n\n### Functions\n\nYou can use regular function in your model. They accept the current state as the first argument, and\n`this` will also be the current state (as long as you don't use hash rocket functions).\n\n```jsx\nconst App = () => {\n  const state = useIbiza({\n    count: 0,\n    increment: state => {\n      ++state.count\n    },\n    decrement() {\n      ++this.count\n    }\n  })\n\n  return (\n    <>\n      <h1>Count = {state.count}</h1>\n      <button onClick={state.increment}>Increment</button>\n      <button onClick={state.decrement}>Decrement</button>\n    </>\n  )\n}\n```\n\nWhen reading/writing state within a function, `this` responds to the state at the level where the\nfunction sits. This means that if the function is deeply nested, `this` will not include state lower\ndown.\n\nTo solve this, you can call `this.$model` to access your model, or `this.$root` to access the root\nof the state.\n\n```javascript\nuseIbiza({\n  deepstate: {\n    user: {\n      name: 'Joel',\n      partner: {\n        name: 'Sam',\n\n        get partner() {\n          // `this` refers to 'deepstate.user.partner'.\n          // `this.$model` refers to 'deepstate.user'.\n          // `this.$root` is the whole store state.\n          return this.$model.name\n        }\n      }\n    }\n  }\n})\n```\n\nFunctions accept any number of arguments just like regular functions do.\n\n```jsx\nconst App = () => {\n  const user = useIbiza({\n    children: [],\n    addChild(state, firstName, lastName) {\n      state.children.push({ firstName, lastName }) // or `this.children.push(...)`\n    }\n  })\n\n  return (\n    <>\n      <ul>\n        {user.children.map((child, i) => (\n          <li key={i}>\n            {child.firstName} {child.lastName}\n          </li>\n        ))}\n      </ul>\n      <button onClick={() => user.addChild('Ash', 'Moss')}></button>\n    </>\n  )\n}\n```\n\n### Getters and Setters\n\nIbiza supports Javascript getters and setters in your state and models.\n\n```javascript\nexport default createModel('user', {\n  firstName: 'Joel',\n  lastName: 'Moss',\n\n  get fullName() {\n    // You can read/write to your state via `this`.\n    return `${this.firstName} ${this.lastName}`\n  },\n\n  set fullName(value) {\n    const [firstName, lastName] = value.split(' ')\n\n    this.firstName = firstName\n    this.lastName = lastName\n  }\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <h1>Hello {user.fullName}</h1>\n      <button onClick={() => void (user.fullName = 'Bob Bones')}></button>\n    </>\n  )\n}\n```\n\n### Async Functions\n\nFunctions can be async and/or return Promises, and support React's Suspense by default.\n\n```javascript\nexport default createModel('user', {\n  name: 'Joel',\n\n  async doSomething() {\n    return await someAsyncAction()\n  }\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <h1>Hello {user.fullName}</h1>\n      <button onClick={user.doSomething}></button>\n    </>\n  )\n}\n```\n\n### URL Models\n\nBecause reading and writing to/from the server is so common, Ibiza has support to make this easy\nwith URL Models, similar to react-query. Simply use a valid and relative URL as you model name or\nslice.\n\nThe following will fetch the user from the server at `/user`, suspending the component while it does\nso. The data is fetched only when it does not exist in the store.\n\n```jsx\nconst App = () => {\n  const user = useIbiza('/user')\n\n  return <h1>Hello {user.name}</h1>\n}\n```\n\nYou can safely mutate your model, as all mutations will remain local.\n\nYou can write your model state back to the server. It the server responds with JSON, the model will\nbe updated with that response.\n\n```jsx\nconst App = () => {\n  const user = useIbiza('/user')\n\n  const renameUser = async () => {\n    await user.save({ body: { name: 'Bob' } })\n  }\n\n  return (\n    <>\n      <h1>Hello {user.name}</h1>\n      <button onClick={() => renameUser()}></button>\n    </>\n  )\n}\n```\n\nURL Models can also be defined with `createModel`:\n\n```javascript\nexport default createModel('/user')\n```\n\n`createModel` returns a hook which you can use. You can now import your model anywhere:\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return <h1>Hello {user.firstName}</h1>\n}\n```\n","_id":"ibiza@1.0.0-beta.3","dist":{"shasum":"6f84d2c45aad0e0b12aa4076296c642b22ae7795","integrity":"sha512-kSMNFDi/gUcG/BGiKmfgleQ/ctR4Q4piyLvEwr3EMELQMdMBUZZiY4qmIqys5o7DsjWTZ27wWbuA0gO35DNRrw==","tarball":"https://registry.npmjs.org/ibiza/-/ibiza-1.0.0-beta.3.tgz","fileCount":21,"unpackedSize":122616,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhltPZCRA9TVsSAnZWagAAOwMP/RUEUzVcrS4I85q0I5vI\nw2igiM3+IB+1mH9v+j+HQr4ByUoyTpHF6XGArprt4/Q8NmvEk4Z+K3lGvN35\n27UK98K6GY9sLdYaNLca31PjeCH1xwA9mfhpu1WSmkgBert2chHWR8YjWXSu\niHe2tExoaXJkuYgRlhva1TkcrPMzXiulAsK6A29HBh8W/d8HlxqkCv8XNgdm\nBHK2UN9lxxCH140MK/fwLKgQdJDs//ILK6Wy9Z87pa+JPKFb33QihNQGId4Y\n4IqHU0eMQ0AG+s3+ZU+wBXqJU9q7FS/ElJyISYrQte3qXSBxykW7Kv+qzJC0\nancadgDN08DfJkLFnMbHIJBuJR8zcLE1A0HwWQ5qvuMiIKAFvZlj+OWHnsf7\n+7vAOKoER5ofuLFD+46pGaj6j+LeWFR+VIoXFFZb/LpYvmtQHrXJFIu5gA9W\nYKiFuu96bKir2PMASqvB5so846m8prHTcEq/MmGkt4bCunXMPZnF8gKCrwFx\n2a6KFk+St8GdoEh29ZemKAuADm6nsaplB9v6wnLYAmqNfc+vzegIBr3taXOk\nRrHBxue+t7y5hKlU3cyfU7GNdd3sRUMOi2cNiAZczJf/KXEBUAxON0MG5ksM\nHKXEPwI0yXcbuSkqHJLjMBKI/1BGxeaDtJ4ofrHZb/pcgBSFS36Agj72zKXm\nOcmC\r\n=sVdC\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDspV5p4t0v3Vfw3uiU5vEVIo2+iOTi0yAMZmJh0Np8gQIgdEnqa8bMnwkHb/Glnagh+pXmbY/CHdKq6jtBibsah/s="}]},"_npmUser":{"name":"joelmoss","email":"joel@developwithstyle.com"},"directories":{},"maintainers":[{"name":"joelmoss","email":"joel@developwithstyle.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ibiza_1.0.0-beta.3_1637274585538_0.10454908985201339"},"_hasShrinkwrap":false},"1.0.0-beta.4":{"name":"ibiza","author":{"name":"Joel Moss"},"version":"1.0.0-beta.4","description":"React State Management for Party Animals","license":"MIT","homepage":"https://github.com/joelmoss/ibiza","repository":{"type":"git","url":"https://github.com/joelmoss/ibiza.git"},"bugs":{"url":"https://github.com/joelmoss/ibiza/issues"},"keywords":["react","state","proxy"],"source":"index.js","browser":"dist/index.cjs","module":"dist/index.js","sideEffects":false,"scripts":{"test":"jest","build":"rollup -c","prepack":"rollup -c","size":"size-limit"},"size-limit":[{"name":"useIbiza","path":"index.js","import":"{ useIbiza }"},{"name":"store","path":"index.js","import":"{ store }"},{"name":"createModel","path":"index.js","import":"{ createModel }"}],"prettier":{"trailingComma":"none","printWidth":100,"semi":false,"singleQuote":true,"arrowParens":"avoid"},"peerDependencies":{"react":">=16"},"devDependencies":{"@babel/core":"^7.16.0","@babel/plugin-transform-runtime":"^7.16.4","@babel/preset-env":"^7.16.4","@babel/preset-react":"^7.16.0","@rollup/plugin-babel":"^5.3.0","@rollup/plugin-node-resolve":"^13.0.6","@size-limit/preset-small-lib":"^7.0.0","@testing-library/jest-dom":"^5.15.0","@testing-library/react":"^12.1.2","@testing-library/react-hooks":"^7.0.2","babel-jest":"^27.3.1","babel-plugin-lodash":"^3.3.4","cross-fetch":"^3.1.4","fetch-mock-jest":"^1.5.1","jest":"^27.3.1","msw":"^0.35.0","parcel":"^2.0.1","react":"^17.0.2","react-dom":"^17.0.2","rollup":"^2.60.0","rollup-plugin-size":"^0.2.2","rollup-plugin-terser":"^7.0.2","size-limit":"^7.0.0"},"dependencies":{"fast-equals":"^2.0.3","lodash":"^4.17.21","micro-memoize":"^4.0.9"},"readmeFilename":"README.md","readme":"# Ibiza - React State Management for Party Animals\n\nIbiza gets out of your way and simply lets you read and write state as you would with regular\nJavascript assignment. It maintains a global state object and is smart enough to know when to\nrerender your components based on state usage and modification.\n\n## How It Works ✨\n\nA component calls the `useIbiza` React hook, which returns the store state as a JS Proxy object.\nThis Proxy records when a state property is accessed or \"used\". Then when that property is mutated,\nthe component is rerendered.\n\nThis means that you can mutate your state in any way, but your component will only rerender if you\nmutate state that you have used.\n\nState can be mutated from anywhere - not just from within a component.\n\nThe following component will rerender when the button is clicked, because `name` has changed.\n\n```jsx\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n      <button onClick={() => void (state.name = 'Joel')}></button>\n    </div>\n  )\n}\n```\n\nThe following component will not rerender when the button is clicked, because even though `age` has\nbeen mutated, it is not actually being used within the component.\n\n```jsx\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n      <button onClick={() => void (state.age = 44)}></button>\n    </div>\n  )\n}\n```\n\n### Initial State\n\nYou can pass some initial state to `useIbiza` which will be merged with existing state in the Ibiza\nstore.\n\n```jsx\nconst App = () => {\n  const state = useIbiza({ user: { name: 'Joel' } })\n\n  return <h1>Hello {state.name}</h1>\n}\n```\n\nThis is safe to include in the body of your component, as it will only be merged into the store on\nfirst render.\n\n### Slicing\n\nIbiza supports deeply nested objects, allowing you to design the shape of your state any way you\nlike. To help you work with such nested state, the `useIbiza` hook supports slicing.\n\nThe following example assumes you have an existing state object:\n\n```javascript\n{\n  user: {\n    name: 'Joel',\n    partner: {\n      name: 'Sam',\n    }\n  }\n}\n```\n\nPass a string to `useIbiza` to fetch a specific slice of state. The string should be the path to the\nobject that you want.\n\n```jsx\nconst App = () => {\n  const partner = useIbiza('user.partner')\n\n  return (\n    <div>\n      <h1>Hello {partner.name}</h1>\n      <button onClick={() => void (partner.name = 'Bob')}></button>\n    </div>\n  )\n}\n```\n\nNote that slicing is really only supported as a convenience, and will not generally help with\nperformance.\n\n### Models\n\nIbiza is at its most powerful when working with models. They provide reusability and flexibility.\n\nCreate a model using the `createModel` helper, where the first argument is the model name, and the\nsecond argument is the initial model state.\n\n```javascript\nexport default createModel('user', {\n  firstName: 'Joel',\n  lastName: 'Moss',\n  children: [{ firstName: 'Ash' }, { firstName: 'Elijah' }, { firstName: 'Eve' }]\n})\n```\n\n`createModel` returns a hook which you can use. You can now import your model anywhere:\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <div>\n      <h1>Hello {user.firstName}</h1>\n      <ul>\n        {user.children.map((child, i) => (\n          <li key={i}>{child.firstName}</li>\n        ))}\n      </ul>\n    </div>\n  )\n}\n```\n\n#### Initial State\n\nSometimes you want to be able to define your model with some initial state that could be provided\ndynamically. For example, from component props or some other parameters.\n\n`createModel` can accept a function as its second argument. This function will be called on\ninitialisation with two arguments; the current `state` and any `props` passed to it when its hook is\nfirst called.\n\n```javascript\nexport default createModel('user', (state, props) => ({\n  firstName: 'Joel',\n  lastName: 'Moss'\n  ...props\n}))\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = ({ yearOfBirth }) => {\n  const user = useModel({ yearOfBirth })\n\n  return (\n    <div>\n      <h1>\n        Hello {user.firstName}, you were born in {user.yearOfBirth}.\n      </h1>\n    </div>\n  )\n}\n```\n\n### Functions\n\nYou can use regular function in your model. They accept the current state as the first argument, and\n`this` will also be the current state (as long as you don't use hash rocket functions).\n\n```jsx\nconst App = () => {\n  const state = useIbiza({\n    count: 0,\n    increment: state => {\n      ++state.count\n    },\n    decrement() {\n      ++this.count\n    }\n  })\n\n  return (\n    <>\n      <h1>Count = {state.count}</h1>\n      <button onClick={state.increment}>Increment</button>\n      <button onClick={state.decrement}>Decrement</button>\n    </>\n  )\n}\n```\n\nWhen reading/writing state within a function, `this` responds to the state at the level where the\nfunction sits. This means that if the function is deeply nested, `this` will not include state lower\ndown.\n\nTo solve this, you can call `this.$model` to access your model, or `this.$root` to access the root\nof the state.\n\n```javascript\nuseIbiza({\n  deepstate: {\n    user: {\n      name: 'Joel',\n      partner: {\n        name: 'Sam',\n\n        get partner() {\n          // `this` refers to 'deepstate.user.partner'.\n          // `this.$model` refers to 'deepstate.user'.\n          // `this.$root` is the whole store state.\n          return this.$model.name\n        }\n      }\n    }\n  }\n})\n```\n\nFunctions accept any number of arguments just like regular functions do.\n\n```jsx\nconst App = () => {\n  const user = useIbiza({\n    children: [],\n    addChild(state, firstName, lastName) {\n      state.children.push({ firstName, lastName }) // or `this.children.push(...)`\n    }\n  })\n\n  return (\n    <>\n      <ul>\n        {user.children.map((child, i) => (\n          <li key={i}>\n            {child.firstName} {child.lastName}\n          </li>\n        ))}\n      </ul>\n      <button onClick={() => user.addChild('Ash', 'Moss')}></button>\n    </>\n  )\n}\n```\n\n### Getters and Setters\n\nIbiza supports Javascript getters and setters in your state and models.\n\n```javascript\nexport default createModel('user', {\n  firstName: 'Joel',\n  lastName: 'Moss',\n\n  get fullName() {\n    // You can read/write to your state via `this`.\n    return `${this.firstName} ${this.lastName}`\n  },\n\n  set fullName(value) {\n    const [firstName, lastName] = value.split(' ')\n\n    this.firstName = firstName\n    this.lastName = lastName\n  }\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <h1>Hello {user.fullName}</h1>\n      <button onClick={() => void (user.fullName = 'Bob Bones')}></button>\n    </>\n  )\n}\n```\n\n### Async Functions\n\nFunctions can be async and/or return Promises, and support React's Suspense by default.\n\n```javascript\nexport default createModel('user', {\n  name: 'Joel',\n\n  async doSomething() {\n    return await someAsyncAction()\n  }\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <h1>Hello {user.fullName}</h1>\n      <button onClick={user.doSomething}></button>\n    </>\n  )\n}\n```\n\n### URL Models\n\nBecause reading and writing to/from the server is so common, Ibiza has support to make this easy\nwith URL Models, similar to react-query. Simply use a valid and relative URL as you model name or\nslice.\n\nThe following will fetch the user from the server at `/user`, suspending the component while it does\nso. The data is fetched only when it does not exist in the store.\n\n```jsx\nconst App = () => {\n  const user = useIbiza('/user')\n\n  return <h1>Hello {user.name}</h1>\n}\n```\n\nYou can safely mutate your model, as all mutations will remain local.\n\nYou can write your model state back to the server. It the server responds with JSON, the model will\nbe updated with that response.\n\n```jsx\nconst App = () => {\n  const user = useIbiza('/user')\n\n  const renameUser = async () => {\n    await user.save({ body: { name: 'Bob' } })\n  }\n\n  return (\n    <>\n      <h1>Hello {user.name}</h1>\n      <button onClick={() => renameUser()}></button>\n    </>\n  )\n}\n```\n\nURL Models can also be defined with `createModel`:\n\n```javascript\nexport default createModel('/user')\n```\n\n`createModel` returns a hook which you can use. You can now import your model anywhere:\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return <h1>Hello {user.firstName}</h1>\n}\n```\n","_id":"ibiza@1.0.0-beta.4","dist":{"shasum":"78964cbd47d6ff69767083082c41e63ce0cba515","integrity":"sha512-ZHMTPaQaiJqXPJbB8XrkKmhGBqiQaI83Eo2u062fnlN6ZYizWQU86cc1Qcy0KclT9irpoDrkuzDfVs/J6X1aLQ==","tarball":"https://registry.npmjs.org/ibiza/-/ibiza-1.0.0-beta.4.tgz","fileCount":21,"unpackedSize":122605,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhltSfCRA9TVsSAnZWagAAje0P/1OIlgh4c+YduRKzTDzW\n/j0iM1sACvUDg74jtdOgeY+KXYXid97qD9uy1/TfVwE0AAF/7xYu/FjWitUv\nbkOwT9G4oA23uzkLG6vgzCc+Aoa24qc48659FdRi9X1BiCMLGuAdTouksCYz\nwRBwbiHoBkRBLwKsCQv9u5X7IiJILLlsecAPjwxj6fApHJG9tTuI+ZwV6Uxu\nQQ7oJ2ULunZW6suHIh91cuL4PnXjuyR3B0/pdKchQRczxqPEObu4n3cc2pgi\n3ZZ/oY1rJAsdYJAGEOvmfzCj9/GrEAG53pY2HheetxGBsm8f3QHVieXjMzIY\nBHBVz07Z4pC0UQlxb9s2kO0ONbiVO27VAKz66n6JlSp9pfbQgUy0xMTiWo9y\nOWRfYI5zmsoVTpKaR2fMA2I8udITkPfSKdJ6qLuZHP+42WSx+hu+/0bPQfrQ\nUABH2nhqpnA0Ext3w0WElDE58f+jY/KNPHn3YijaDpxb6qNPo6YSyviABq2+\n8I/KW8H16fzsFKZWolhSQaowpzHVrMgjRvb03nw8LUIO4BvYfKHLT0l7P1eP\nalRpweD804Q+j6WM8K5tIzyXmPTtjyMLa+4zp/JMmkUOINVSgaNR4B8iOZJd\nUXj26tpQWAli7q/naq8QfuNVLON/o/T6rOHYtAh6Zdp9lcxz0r+XgpLPxNDm\nRdK5\r\n=9m0e\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEEXLIvNZAkB1v1XQmo92wb/nqW7Bw9Zs++zWhOrVi2iAiEAxQjndM+hCt/yxwojPunyX3Zs8fvBMzDAHzcaxVfqQaA="}]},"_npmUser":{"name":"joelmoss","email":"joel@developwithstyle.com"},"directories":{},"maintainers":[{"name":"joelmoss","email":"joel@developwithstyle.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ibiza_1.0.0-beta.4_1637274783090_0.5829861790530608"},"_hasShrinkwrap":false},"1.0.0-beta.5":{"name":"ibiza","author":{"name":"Joel Moss"},"version":"1.0.0-beta.5","description":"React State Management for Party Animals","license":"MIT","homepage":"https://github.com/joelmoss/ibiza","repository":{"type":"git","url":"https://github.com/joelmoss/ibiza.git"},"bugs":{"url":"https://github.com/joelmoss/ibiza/issues"},"keywords":["react","state","proxy"],"source":"index.js","main":"dist/index.cjs","module":"dist/index.js","sideEffects":false,"scripts":{"test":"jest","build":"rollup -c","prepack":"rollup -c","size":"size-limit"},"size-limit":[{"name":"useIbiza","path":"index.js","import":"{ useIbiza }"},{"name":"store","path":"index.js","import":"{ store }"},{"name":"createModel","path":"index.js","import":"{ createModel }"}],"prettier":{"trailingComma":"none","printWidth":100,"semi":false,"singleQuote":true,"arrowParens":"avoid"},"peerDependencies":{"react":">=16"},"devDependencies":{"@babel/core":"^7.16.0","@babel/plugin-transform-runtime":"^7.16.4","@babel/preset-env":"^7.16.4","@babel/preset-react":"^7.16.0","@rollup/plugin-babel":"^5.3.0","@rollup/plugin-node-resolve":"^13.0.6","@size-limit/preset-small-lib":"^7.0.0","@testing-library/jest-dom":"^5.15.0","@testing-library/react":"^12.1.2","@testing-library/react-hooks":"^7.0.2","babel-jest":"^27.3.1","babel-plugin-lodash":"^3.3.4","cross-fetch":"^3.1.4","fetch-mock-jest":"^1.5.1","jest":"^27.3.1","msw":"^0.35.0","parcel":"^2.0.1","react":"^17.0.2","react-dom":"^17.0.2","rollup":"^2.60.0","rollup-plugin-size":"^0.2.2","rollup-plugin-terser":"^7.0.2","size-limit":"^7.0.0"},"dependencies":{"fast-equals":"^2.0.3","lodash":"^4.17.21","micro-memoize":"^4.0.9"},"readmeFilename":"README.md","readme":"# Ibiza - React State Management for Party Animals\n\nIbiza gets out of your way and simply lets you read and write state as you would with regular\nJavascript assignment. It maintains a global state object and is smart enough to know when to\nrerender your components based on state usage and modification.\n\n## How It Works ✨\n\nA component calls the `useIbiza` React hook, which returns the store state as a JS Proxy object.\nThis Proxy records when a state property is accessed or \"used\". Then when that property is mutated,\nthe component is rerendered.\n\nThis means that you can mutate your state in any way, but your component will only rerender if you\nmutate state that you have used.\n\nState can be mutated from anywhere - not just from within a component.\n\nThe following component will rerender when the button is clicked, because `name` has changed.\n\n```jsx\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n      <button onClick={() => void (state.name = 'Joel')}></button>\n    </div>\n  )\n}\n```\n\nThe following component will not rerender when the button is clicked, because even though `age` has\nbeen mutated, it is not actually being used within the component.\n\n```jsx\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n      <button onClick={() => void (state.age = 44)}></button>\n    </div>\n  )\n}\n```\n\n### Initial State\n\nYou can pass some initial state to `useIbiza` which will be merged with existing state in the Ibiza\nstore.\n\n```jsx\nconst App = () => {\n  const state = useIbiza({ user: { name: 'Joel' } })\n\n  return <h1>Hello {state.name}</h1>\n}\n```\n\nThis is safe to include in the body of your component, as it will only be merged into the store on\nfirst render.\n\n### Slicing\n\nIbiza supports deeply nested objects, allowing you to design the shape of your state any way you\nlike. To help you work with such nested state, the `useIbiza` hook supports slicing.\n\nThe following example assumes you have an existing state object:\n\n```javascript\n{\n  user: {\n    name: 'Joel',\n    partner: {\n      name: 'Sam',\n    }\n  }\n}\n```\n\nPass a string to `useIbiza` to fetch a specific slice of state. The string should be the path to the\nobject that you want.\n\n```jsx\nconst App = () => {\n  const partner = useIbiza('user.partner')\n\n  return (\n    <div>\n      <h1>Hello {partner.name}</h1>\n      <button onClick={() => void (partner.name = 'Bob')}></button>\n    </div>\n  )\n}\n```\n\nNote that slicing is really only supported as a convenience, and will not generally help with\nperformance.\n\n### Models\n\nIbiza is at its most powerful when working with models. They provide reusability and flexibility.\n\nCreate a model using the `createModel` helper, where the first argument is the model name, and the\nsecond argument is the initial model state.\n\n```javascript\nexport default createModel('user', {\n  firstName: 'Joel',\n  lastName: 'Moss',\n  children: [{ firstName: 'Ash' }, { firstName: 'Elijah' }, { firstName: 'Eve' }]\n})\n```\n\n`createModel` returns a hook which you can use. You can now import your model anywhere:\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <div>\n      <h1>Hello {user.firstName}</h1>\n      <ul>\n        {user.children.map((child, i) => (\n          <li key={i}>{child.firstName}</li>\n        ))}\n      </ul>\n    </div>\n  )\n}\n```\n\n#### Initial State\n\nSometimes you want to be able to define your model with some initial state that could be provided\ndynamically. For example, from component props or some other parameters.\n\n`createModel` can accept a function as its second argument. This function will be called on\ninitialisation with two arguments; the current `state` and any `props` passed to it when its hook is\nfirst called.\n\n```javascript\nexport default createModel('user', (state, props) => ({\n  firstName: 'Joel',\n  lastName: 'Moss'\n  ...props\n}))\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = ({ yearOfBirth }) => {\n  const user = useModel({ yearOfBirth })\n\n  return (\n    <div>\n      <h1>\n        Hello {user.firstName}, you were born in {user.yearOfBirth}.\n      </h1>\n    </div>\n  )\n}\n```\n\n### Functions\n\nYou can use regular function in your model. They accept the current state as the first argument, and\n`this` will also be the current state (as long as you don't use hash rocket functions).\n\n```jsx\nconst App = () => {\n  const state = useIbiza({\n    count: 0,\n    increment: state => {\n      ++state.count\n    },\n    decrement() {\n      ++this.count\n    }\n  })\n\n  return (\n    <>\n      <h1>Count = {state.count}</h1>\n      <button onClick={state.increment}>Increment</button>\n      <button onClick={state.decrement}>Decrement</button>\n    </>\n  )\n}\n```\n\nWhen reading/writing state within a function, `this` responds to the state at the level where the\nfunction sits. This means that if the function is deeply nested, `this` will not include state lower\ndown.\n\nTo solve this, you can call `this.$model` to access your model, or `this.$root` to access the root\nof the state.\n\n```javascript\nuseIbiza({\n  deepstate: {\n    user: {\n      name: 'Joel',\n      partner: {\n        name: 'Sam',\n\n        get partner() {\n          // `this` refers to 'deepstate.user.partner'.\n          // `this.$model` refers to 'deepstate.user'.\n          // `this.$root` is the whole store state.\n          return this.$model.name\n        }\n      }\n    }\n  }\n})\n```\n\nFunctions accept any number of arguments just like regular functions do.\n\n```jsx\nconst App = () => {\n  const user = useIbiza({\n    children: [],\n    addChild(state, firstName, lastName) {\n      state.children.push({ firstName, lastName }) // or `this.children.push(...)`\n    }\n  })\n\n  return (\n    <>\n      <ul>\n        {user.children.map((child, i) => (\n          <li key={i}>\n            {child.firstName} {child.lastName}\n          </li>\n        ))}\n      </ul>\n      <button onClick={() => user.addChild('Ash', 'Moss')}></button>\n    </>\n  )\n}\n```\n\n### Getters and Setters\n\nIbiza supports Javascript getters and setters in your state and models.\n\n```javascript\nexport default createModel('user', {\n  firstName: 'Joel',\n  lastName: 'Moss',\n\n  get fullName() {\n    // You can read/write to your state via `this`.\n    return `${this.firstName} ${this.lastName}`\n  },\n\n  set fullName(value) {\n    const [firstName, lastName] = value.split(' ')\n\n    this.firstName = firstName\n    this.lastName = lastName\n  }\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <h1>Hello {user.fullName}</h1>\n      <button onClick={() => void (user.fullName = 'Bob Bones')}></button>\n    </>\n  )\n}\n```\n\n### Async Functions\n\nFunctions can be async and/or return Promises, and support React's Suspense by default.\n\n```javascript\nexport default createModel('user', {\n  name: 'Joel',\n\n  async doSomething() {\n    return await someAsyncAction()\n  }\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <h1>Hello {user.fullName}</h1>\n      <button onClick={user.doSomething}></button>\n    </>\n  )\n}\n```\n\n### URL Models\n\nBecause reading and writing to/from the server is so common, Ibiza has support to make this easy\nwith URL Models, similar to react-query. Simply use a valid and relative URL as you model name or\nslice.\n\nThe following will fetch the user from the server at `/user`, suspending the component while it does\nso. The data is fetched only when it does not exist in the store.\n\n```jsx\nconst App = () => {\n  const user = useIbiza('/user')\n\n  return <h1>Hello {user.name}</h1>\n}\n```\n\nYou can safely mutate your model, as all mutations will remain local.\n\nYou can write your model state back to the server. It the server responds with JSON, the model will\nbe updated with that response.\n\n```jsx\nconst App = () => {\n  const user = useIbiza('/user')\n\n  const renameUser = async () => {\n    await user.save({ body: { name: 'Bob' } })\n  }\n\n  return (\n    <>\n      <h1>Hello {user.name}</h1>\n      <button onClick={() => renameUser()}></button>\n    </>\n  )\n}\n```\n\nURL Models can also be defined with `createModel`:\n\n```javascript\nexport default createModel('/user')\n```\n\n`createModel` returns a hook which you can use. You can now import your model anywhere:\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return <h1>Hello {user.firstName}</h1>\n}\n```\n","_id":"ibiza@1.0.0-beta.5","dist":{"shasum":"3bd79d50be786bec57b11f4786da2280876441bf","integrity":"sha512-k+MDmWxhM+OWahs4WzbkMY9Q+BX8X56B36kbRfWyGPNS/nhwWYdYiBd4mf64zyu2kCoVnBYcIvCKiLBAMjtSqA==","tarball":"https://registry.npmjs.org/ibiza/-/ibiza-1.0.0-beta.5.tgz","fileCount":21,"unpackedSize":212135,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhltYKCRA9TVsSAnZWagAAhZsP/iEskHDOxx+hkPYiKV+d\nLVIJdjfFFidfi/p+QwI6FIx0tuoPd2RjioAOMsrLq8kfJZZsF5AG3SYq9HNf\n7HVmADS7Zce6/kmknUHzQsYvbJZmrljGe84u4aCP3awRH9zmLxFOWHvZTrZK\nDviiWJCpLHFk+gYm8Pi8HlUktnGD07Nh+pAQnt+ffyi/KIDN7Udm9XMU8Iad\nEDmajoSISne5ea+nL/9O5hCIKT6Nkxpm8O34khpbhRFRYckIC8cw5Y/DW3BL\n9OSWpt9zresiygRBlZvcdv4BQ3rhyJxNKQaRZ5slRz3ZQp59Gigj1Y4jsPav\nlZchL49CEOHUqzYw6Qd0522NzkuFzrzgrdW/VCOQURALpIo6ZArBpX4BQbZb\nT3W1t7KpHI2G77uwbhvcF9f6OPRlRWvEST3ls5QyEzqw/6+g3wkXR6fj2Dn5\nJmzFfJ7tgX8/JlkWR514VG8vf0ZSO1tBanwTvh7d+J2UGJLzGZqDFgw8NwDd\n+54eVDhCrxyBWPrbFgmNZZCU05nNKR49vFBvCUdKsYwJ4+aX3QvQaDL/Eh7b\nN1JQ24zBtEM3EjoO3BRlMCyX3MaZfGQLqqw2yZh4pVnUsTTzNUWHMNlI1g5f\nQ4FuPGkvSuyCDDgVJ4uAYqUP1W08neuTAD/Tcz0h4arG0QrU7wJhmw+cAU3J\n7+w3\r\n=wDC/\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEPLer7alOH2ww0daF2F294hx/6DgcKc14V+RjkzvfdRAiBYPKmBzwajMj0EPY7hyHTZ5dKsoJuoh1LnF5vYuLRiXA=="}]},"_npmUser":{"name":"joelmoss","email":"joel@developwithstyle.com"},"directories":{},"maintainers":[{"name":"joelmoss","email":"joel@developwithstyle.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ibiza_1.0.0-beta.5_1637275146290_0.30838212976107915"},"_hasShrinkwrap":false},"1.0.0-beta.6":{"name":"ibiza","author":{"name":"Joel Moss"},"version":"1.0.0-beta.6","description":"React State Management for Party Animals","license":"MIT","homepage":"https://github.com/joelmoss/ibiza","repository":{"type":"git","url":"https://github.com/joelmoss/ibiza.git"},"bugs":{"url":"https://github.com/joelmoss/ibiza/issues"},"keywords":["react","state","proxy"],"source":"index.js","main":"dist/index.cjs","module":"dist/index.js","sideEffects":false,"scripts":{"test":"jest","build":"rollup -c","prepack":"rollup -c","size":"size-limit"},"size-limit":[{"name":"useIbiza","path":"index.js","import":"{ useIbiza }"},{"name":"store","path":"index.js","import":"{ store }"},{"name":"createModel","path":"index.js","import":"{ createModel }"}],"prettier":{"trailingComma":"none","printWidth":100,"semi":false,"singleQuote":true,"arrowParens":"avoid"},"peerDependencies":{"react":">=16"},"devDependencies":{"@babel/core":"^7.16.0","@babel/plugin-transform-runtime":"^7.16.4","@babel/preset-env":"^7.16.4","@babel/preset-react":"^7.16.0","@rollup/plugin-babel":"^5.3.0","@rollup/plugin-node-resolve":"^13.0.6","@size-limit/preset-small-lib":"^7.0.0","@testing-library/jest-dom":"^5.15.0","@testing-library/react":"^12.1.2","@testing-library/react-hooks":"^7.0.2","babel-jest":"^27.3.1","babel-plugin-lodash":"^3.3.4","cross-fetch":"^3.1.4","fetch-mock-jest":"^1.5.1","jest":"^27.3.1","msw":"^0.35.0","parcel":"^2.0.1","react":"^17.0.2","react-dom":"^17.0.2","rollup":"^2.60.0","rollup-plugin-size":"^0.2.2","size-limit":"^7.0.0"},"dependencies":{"fast-equals":"^2.0.3","lodash":"^4.17.21","micro-memoize":"^4.0.9"},"readmeFilename":"README.md","readme":"# Ibiza - React State Management for Party Animals\n\nIbiza gets out of your way and simply lets you read and write state as you would with regular\nJavascript assignment. It maintains a global state object and is smart enough to know when to\nrerender your components based on state usage and modification.\n\n## How It Works ✨\n\nA component calls the `useIbiza` React hook, which returns the store state as a JS Proxy object.\nThis Proxy records when a state property is accessed or \"used\". Then when that property is mutated,\nthe component is rerendered.\n\nThis means that you can mutate your state in any way, but your component will only rerender if you\nmutate state that you have used.\n\nState can be mutated from anywhere - not just from within a component.\n\nThe following component will rerender when the button is clicked, because `name` has changed.\n\n```jsx\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n      <button onClick={() => void (state.name = 'Joel')}></button>\n    </div>\n  )\n}\n```\n\nThe following component will not rerender when the button is clicked, because even though `age` has\nbeen mutated, it is not actually being used within the component.\n\n```jsx\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n      <button onClick={() => void (state.age = 44)}></button>\n    </div>\n  )\n}\n```\n\n### Initial State\n\nYou can pass some initial state to `useIbiza` which will be merged with existing state in the Ibiza\nstore.\n\n```jsx\nconst App = () => {\n  const state = useIbiza({ user: { name: 'Joel' } })\n\n  return <h1>Hello {state.name}</h1>\n}\n```\n\nThis is safe to include in the body of your component, as it will only be merged into the store on\nfirst render.\n\n### Slicing\n\nIbiza supports deeply nested objects, allowing you to design the shape of your state any way you\nlike. To help you work with such nested state, the `useIbiza` hook supports slicing.\n\nThe following example assumes you have an existing state object:\n\n```javascript\n{\n  user: {\n    name: 'Joel',\n    partner: {\n      name: 'Sam',\n    }\n  }\n}\n```\n\nPass a string to `useIbiza` to fetch a specific slice of state. The string should be the path to the\nobject that you want.\n\n```jsx\nconst App = () => {\n  const partner = useIbiza('user.partner')\n\n  return (\n    <div>\n      <h1>Hello {partner.name}</h1>\n      <button onClick={() => void (partner.name = 'Bob')}></button>\n    </div>\n  )\n}\n```\n\nNote that slicing is really only supported as a convenience, and will not generally help with\nperformance.\n\n### Models\n\nIbiza is at its most powerful when working with models. They provide reusability and flexibility.\n\nCreate a model using the `createModel` helper, where the first argument is the model name, and the\nsecond argument is the initial model state.\n\n```javascript\nexport default createModel('user', {\n  firstName: 'Joel',\n  lastName: 'Moss',\n  children: [{ firstName: 'Ash' }, { firstName: 'Elijah' }, { firstName: 'Eve' }]\n})\n```\n\n`createModel` returns a hook which you can use. You can now import your model anywhere:\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <div>\n      <h1>Hello {user.firstName}</h1>\n      <ul>\n        {user.children.map((child, i) => (\n          <li key={i}>{child.firstName}</li>\n        ))}\n      </ul>\n    </div>\n  )\n}\n```\n\n#### Initial State\n\nSometimes you want to be able to define your model with some initial state that could be provided\ndynamically. For example, from component props or some other parameters.\n\n`createModel` can accept a function as its second argument. This function will be called on\ninitialisation with two arguments; the current `state` and any `props` passed to it when its hook is\nfirst called.\n\n```javascript\nexport default createModel('user', (state, props) => ({\n  firstName: 'Joel',\n  lastName: 'Moss'\n  ...props\n}))\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = ({ yearOfBirth }) => {\n  const user = useModel({ yearOfBirth })\n\n  return (\n    <div>\n      <h1>\n        Hello {user.firstName}, you were born in {user.yearOfBirth}.\n      </h1>\n    </div>\n  )\n}\n```\n\n### Functions\n\nYou can use regular function in your model. They accept the current state as the first argument, and\n`this` will also be the current state (as long as you don't use hash rocket functions).\n\n```jsx\nconst App = () => {\n  const state = useIbiza({\n    count: 0,\n    increment: state => {\n      ++state.count\n    },\n    decrement() {\n      ++this.count\n    }\n  })\n\n  return (\n    <>\n      <h1>Count = {state.count}</h1>\n      <button onClick={state.increment}>Increment</button>\n      <button onClick={state.decrement}>Decrement</button>\n    </>\n  )\n}\n```\n\nWhen reading/writing state within a function, `this` responds to the state at the level where the\nfunction sits. This means that if the function is deeply nested, `this` will not include state lower\ndown.\n\nTo solve this, you can call `this.$model` to access your model, or `this.$root` to access the root\nof the state.\n\n```javascript\nuseIbiza({\n  deepstate: {\n    user: {\n      name: 'Joel',\n      partner: {\n        name: 'Sam',\n\n        get partner() {\n          // `this` refers to 'deepstate.user.partner'.\n          // `this.$model` refers to 'deepstate.user'.\n          // `this.$root` is the whole store state.\n          return this.$model.name\n        }\n      }\n    }\n  }\n})\n```\n\nFunctions accept any number of arguments just like regular functions do.\n\n```jsx\nconst App = () => {\n  const user = useIbiza({\n    children: [],\n    addChild(state, firstName, lastName) {\n      state.children.push({ firstName, lastName }) // or `this.children.push(...)`\n    }\n  })\n\n  return (\n    <>\n      <ul>\n        {user.children.map((child, i) => (\n          <li key={i}>\n            {child.firstName} {child.lastName}\n          </li>\n        ))}\n      </ul>\n      <button onClick={() => user.addChild('Ash', 'Moss')}></button>\n    </>\n  )\n}\n```\n\n### Getters and Setters\n\nIbiza supports Javascript getters and setters in your state and models.\n\n```javascript\nexport default createModel('user', {\n  firstName: 'Joel',\n  lastName: 'Moss',\n\n  get fullName() {\n    // You can read/write to your state via `this`.\n    return `${this.firstName} ${this.lastName}`\n  },\n\n  set fullName(value) {\n    const [firstName, lastName] = value.split(' ')\n\n    this.firstName = firstName\n    this.lastName = lastName\n  }\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <h1>Hello {user.fullName}</h1>\n      <button onClick={() => void (user.fullName = 'Bob Bones')}></button>\n    </>\n  )\n}\n```\n\n### Async Functions\n\nFunctions can be async and/or return Promises, and support React's Suspense by default.\n\n```javascript\nexport default createModel('user', {\n  name: 'Joel',\n\n  async doSomething() {\n    return await someAsyncAction()\n  }\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <h1>Hello {user.fullName}</h1>\n      <button onClick={user.doSomething}></button>\n    </>\n  )\n}\n```\n\n### URL Models\n\nBecause reading and writing to/from the server is so common, Ibiza has support to make this easy\nwith URL Models, similar to react-query. Simply use a valid and relative URL as you model name or\nslice.\n\nThe following will fetch the user from the server at `/user`, suspending the component while it does\nso. The data is fetched only when it does not exist in the store.\n\n```jsx\nconst App = () => {\n  const user = useIbiza('/user')\n\n  return <h1>Hello {user.name}</h1>\n}\n```\n\nYou can safely mutate your model, as all mutations will remain local.\n\nYou can write your model state back to the server. It the server responds with JSON, the model will\nbe updated with that response.\n\n```jsx\nconst App = () => {\n  const user = useIbiza('/user')\n\n  const renameUser = async () => {\n    await user.save({ body: { name: 'Bob' } })\n  }\n\n  return (\n    <>\n      <h1>Hello {user.name}</h1>\n      <button onClick={() => renameUser()}></button>\n    </>\n  )\n}\n```\n\nURL Models can also be defined with `createModel`:\n\n```javascript\nexport default createModel('/user')\n```\n\n`createModel` returns a hook which you can use. You can now import your model anywhere:\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return <h1>Hello {user.firstName}</h1>\n}\n```\n","_id":"ibiza@1.0.0-beta.6","dist":{"shasum":"5defacc4a733998f486f9f8983b4be2515e5184a","integrity":"sha512-ms+AbolK6VK61lb9AlOJA/L1BtJRKrinQyp8yjn5g1jyBcSk6JyBzcdCDpd3eVlYKICfPRooQhvZUBlNdpNt1Q==","tarball":"https://registry.npmjs.org/ibiza/-/ibiza-1.0.0-beta.6.tgz","fileCount":21,"unpackedSize":271476,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhltdlCRA9TVsSAnZWagAAV7EQAI6XprONr3aIXBVnDSPl\ncAG5r60LBDJ8Ce9Z85JLOWzHKW6dKkxJxiaBztJzii+DsY30/Vb9knF6HQeq\nfkrZug/+Oi5XiqvVe9UdOqBZ9JHxF8AwezPcPsyWTV1lMYW+Y3QMbfT0hLtk\nOTZ4NV0tA+FaBzm1vCyOEV60MWBjf6RNKxTfcBjgZB7ZgUXGeNZ1OAAarbCG\nWHIEhlIwaL7QNxbEWaw3ysbYenPC/choVT7ZLXdcLpWrjrnup+niB5mLtUaL\nO7JFSjgJtrtg0aUvRrb4IFOrj7Zrgm2Clbt9ZtTS7Wkvyqk+5Snw5Z3F4J/V\n5cqjXBzqKwP6zwV/ixlba1mhI3nY/aImBYQ/uHDTuDmWHHinR7iRPgTdRORe\nz1ck81hhUtBfqI2xNoaCmN8jsfl/rF24pa9wGvNcOVrQBOIapD0l2k7yk4EQ\nCYobin186L0AVuA8jIbIYLP960xs+4oOJFK9k2nsQAh9oE5/l0jRrOW6h7fi\nDs6qFtjxonVGRDHxX3DEri+XbuiDWq0ZqETomqBTw8uKGyK7fH7Qm6hMTF+A\n0d99mbq/fbGfcIUGLrWhIlO0WawVMdSt974bhv02NQwULEQG6Bq1b/8Aru7J\nLLnSxufMTD+YIfIx1RCG7QB2g7+O7O5enlN/eyiDFenr8OvSmUFSfsfdtuiM\nPvRM\r\n=QLh6\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC/2Fz/fp8cl5noG6g1lNvsQQ1PCyNVweCJZQLqci6/kwIgTFIzbileXGUbYLb1oD2e/0gVA5WL4wBQaNPdP9hdpIE="}]},"_npmUser":{"name":"joelmoss","email":"joel@developwithstyle.com"},"directories":{},"maintainers":[{"name":"joelmoss","email":"joel@developwithstyle.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ibiza_1.0.0-beta.6_1637275492790_0.21987348060704903"},"_hasShrinkwrap":false},"1.0.0-beta.7":{"name":"ibiza","author":{"name":"Joel Moss"},"version":"1.0.0-beta.7","description":"React State Management for Party Animals","license":"MIT","homepage":"https://github.com/joelmoss/ibiza","repository":{"type":"git","url":"https://github.com/joelmoss/ibiza.git"},"bugs":{"url":"https://github.com/joelmoss/ibiza/issues"},"keywords":["react","state","proxy"],"source":"index.js","main":"dist/index.cjs","module":"dist/index.js","sideEffects":false,"scripts":{"test":"jest","build":"rollup -c","prepack":"rollup -c","size":"size-limit"},"size-limit":[{"name":"useIbiza","path":"index.js","import":"{ useIbiza }"},{"name":"store","path":"index.js","import":"{ store }"},{"name":"createModel","path":"index.js","import":"{ createModel }"}],"prettier":{"trailingComma":"none","printWidth":100,"semi":false,"singleQuote":true,"arrowParens":"avoid"},"peerDependencies":{"react":">=16"},"devDependencies":{"@babel/core":"^7.16.0","@babel/plugin-transform-runtime":"^7.16.4","@babel/preset-env":"^7.16.4","@babel/preset-react":"^7.16.0","@rollup/plugin-babel":"^5.3.0","@rollup/plugin-node-resolve":"^13.0.6","@size-limit/preset-small-lib":"^7.0.0","@testing-library/jest-dom":"^5.15.0","@testing-library/react":"^12.1.2","@testing-library/react-hooks":"^7.0.2","babel-jest":"^27.3.1","babel-plugin-lodash":"^3.3.4","cross-fetch":"^3.1.4","fetch-mock-jest":"^1.5.1","jest":"^27.3.1","msw":"^0.35.0","parcel":"^2.0.1","react":"^17.0.2","react-dom":"^17.0.2","rollup":"^2.60.0","rollup-plugin-size":"^0.2.2","size-limit":"^7.0.0"},"dependencies":{"fast-equals":"^2.0.3","lodash":"^4.17.21","micro-memoize":"^4.0.9"},"readmeFilename":"README.md","readme":"# Ibiza - React State Management for Party Animals\n\nIbiza gets out of your way and simply lets you read and write state as you would with regular\nJavascript assignment. It maintains a global state object and is smart enough to know when to\nrerender your components based on state usage and modification.\n\n## How It Works ✨\n\nA component calls the `useIbiza` React hook, which returns the store state as a JS Proxy object.\nThis Proxy records when a state property is accessed or \"used\". Then when that property is mutated,\nthe component is rerendered.\n\nThis means that you can mutate your state in any way, but your component will only rerender if you\nmutate state that you have used.\n\nState can be mutated from anywhere - not just from within a component.\n\nThe following component will rerender when the button is clicked, because `name` has changed.\n\n```jsx\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n      <button onClick={() => void (state.name = 'Joel')}></button>\n    </div>\n  )\n}\n```\n\nThe following component will not rerender when the button is clicked, because even though `age` has\nbeen mutated, it is not actually being used within the component.\n\n```jsx\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n      <button onClick={() => void (state.age = 44)}></button>\n    </div>\n  )\n}\n```\n\n### Initial State\n\nYou can pass some initial state to `useIbiza` which will be merged with existing state in the Ibiza\nstore.\n\n```jsx\nconst App = () => {\n  const state = useIbiza({ user: { name: 'Joel' } })\n\n  return <h1>Hello {state.name}</h1>\n}\n```\n\nThis is safe to include in the body of your component, as it will only be merged into the store on\nfirst render.\n\n### Slicing\n\nIbiza supports deeply nested objects, allowing you to design the shape of your state any way you\nlike. To help you work with such nested state, the `useIbiza` hook supports slicing.\n\nThe following example assumes you have an existing state object:\n\n```javascript\n{\n  user: {\n    name: 'Joel',\n    partner: {\n      name: 'Sam',\n    }\n  }\n}\n```\n\nPass a string to `useIbiza` to fetch a specific slice of state. The string should be the path to the\nobject that you want.\n\n```jsx\nconst App = () => {\n  const partner = useIbiza('user.partner')\n\n  return (\n    <div>\n      <h1>Hello {partner.name}</h1>\n      <button onClick={() => void (partner.name = 'Bob')}></button>\n    </div>\n  )\n}\n```\n\nNote that slicing is really only supported as a convenience, and will not generally help with\nperformance.\n\n### Models\n\nIbiza is at its most powerful when working with models. They provide reusability and flexibility.\n\nCreate a model using the `createModel` helper, where the first argument is the model name, and the\nsecond argument is the initial model state.\n\n```javascript\nexport default createModel('user', {\n  firstName: 'Joel',\n  lastName: 'Moss',\n  children: [{ firstName: 'Ash' }, { firstName: 'Elijah' }, { firstName: 'Eve' }]\n})\n```\n\n`createModel` returns a hook which you can use. You can now import your model anywhere:\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <div>\n      <h1>Hello {user.firstName}</h1>\n      <ul>\n        {user.children.map((child, i) => (\n          <li key={i}>{child.firstName}</li>\n        ))}\n      </ul>\n    </div>\n  )\n}\n```\n\n#### Initial State\n\nSometimes you want to be able to define your model with some initial state that could be provided\ndynamically. For example, from component props or some other parameters.\n\n`createModel` can accept a function as its second argument. This function will be called on\ninitialisation with two arguments; the current `state` and any `props` passed to it when its hook is\nfirst called.\n\n```javascript\nexport default createModel('user', (state, props) => ({\n  firstName: 'Joel',\n  lastName: 'Moss'\n  ...props\n}))\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = ({ yearOfBirth }) => {\n  const user = useModel({ yearOfBirth })\n\n  return (\n    <div>\n      <h1>\n        Hello {user.firstName}, you were born in {user.yearOfBirth}.\n      </h1>\n    </div>\n  )\n}\n```\n\n### Functions\n\nYou can use regular function in your model. They accept the current state as the first argument, and\n`this` will also be the current state (as long as you don't use hash rocket functions).\n\n```jsx\nconst App = () => {\n  const state = useIbiza({\n    count: 0,\n    increment: state => {\n      ++state.count\n    },\n    decrement() {\n      ++this.count\n    }\n  })\n\n  return (\n    <>\n      <h1>Count = {state.count}</h1>\n      <button onClick={state.increment}>Increment</button>\n      <button onClick={state.decrement}>Decrement</button>\n    </>\n  )\n}\n```\n\nWhen reading/writing state within a function, `this` responds to the state at the level where the\nfunction sits. This means that if the function is deeply nested, `this` will not include state lower\ndown.\n\nTo solve this, you can call `this.$model` to access your model, or `this.$root` to access the root\nof the state.\n\n```javascript\nuseIbiza({\n  deepstate: {\n    user: {\n      name: 'Joel',\n      partner: {\n        name: 'Sam',\n\n        get partner() {\n          // `this` refers to 'deepstate.user.partner'.\n          // `this.$model` refers to 'deepstate.user'.\n          // `this.$root` is the whole store state.\n          return this.$model.name\n        }\n      }\n    }\n  }\n})\n```\n\nFunctions accept any number of arguments just like regular functions do.\n\n```jsx\nconst App = () => {\n  const user = useIbiza({\n    children: [],\n    addChild(state, firstName, lastName) {\n      state.children.push({ firstName, lastName }) // or `this.children.push(...)`\n    }\n  })\n\n  return (\n    <>\n      <ul>\n        {user.children.map((child, i) => (\n          <li key={i}>\n            {child.firstName} {child.lastName}\n          </li>\n        ))}\n      </ul>\n      <button onClick={() => user.addChild('Ash', 'Moss')}></button>\n    </>\n  )\n}\n```\n\n### Getters and Setters\n\nIbiza supports Javascript getters and setters in your state and models.\n\n```javascript\nexport default createModel('user', {\n  firstName: 'Joel',\n  lastName: 'Moss',\n\n  get fullName() {\n    // You can read/write to your state via `this`.\n    return `${this.firstName} ${this.lastName}`\n  },\n\n  set fullName(value) {\n    const [firstName, lastName] = value.split(' ')\n\n    this.firstName = firstName\n    this.lastName = lastName\n  }\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <h1>Hello {user.fullName}</h1>\n      <button onClick={() => void (user.fullName = 'Bob Bones')}></button>\n    </>\n  )\n}\n```\n\n### Async Functions\n\nFunctions can be async and/or return Promises, and support React's Suspense by default.\n\n```javascript\nexport default createModel('user', {\n  name: 'Joel',\n\n  async doSomething() {\n    return await someAsyncAction()\n  }\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <h1>Hello {user.fullName}</h1>\n      <button onClick={user.doSomething}></button>\n    </>\n  )\n}\n```\n\n### URL Models\n\nBecause reading and writing to/from the server is so common, Ibiza has support to make this easy\nwith URL Models, similar to react-query. Simply use a valid and relative URL as you model name or\nslice.\n\nThe following will fetch the user from the server at `/user`, suspending the component while it does\nso. The data is fetched only when it does not exist in the store.\n\n```jsx\nconst App = () => {\n  const user = useIbiza('/user')\n\n  return <h1>Hello {user.name}</h1>\n}\n```\n\nYou can safely mutate your model, as all mutations will remain local.\n\nYou can write your model state back to the server. It the server responds with JSON, the model will\nbe updated with that response.\n\n```jsx\nconst App = () => {\n  const user = useIbiza('/user')\n\n  const renameUser = async () => {\n    await user.save({ body: { name: 'Bob' } })\n  }\n\n  return (\n    <>\n      <h1>Hello {user.name}</h1>\n      <button onClick={() => renameUser()}></button>\n    </>\n  )\n}\n```\n\nURL Models can also be defined with `createModel`:\n\n```javascript\nexport default createModel('/user')\n```\n\n`createModel` returns a hook which you can use. You can now import your model anywhere:\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return <h1>Hello {user.firstName}</h1>\n}\n```\n","_id":"ibiza@1.0.0-beta.7","dist":{"shasum":"fd565099f8e08f39beb9dbd35b6ec9476dcfa164","integrity":"sha512-WOrtLglmVtHVqtVSrDgwMyLkovPpARnXT3lQ0Ec+psVczc49OIG1Y39WXvD0XmPSVS+hQGqluP4+J/rxa/POWA==","tarball":"https://registry.npmjs.org/ibiza/-/ibiza-1.0.0-beta.7.tgz","fileCount":21,"unpackedSize":271840,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhltsRCRA9TVsSAnZWagAAckMQAJGzyTlDg6EMmR7IvC7o\nmRQOIW+prAlMX6AM0fYPFcRPPthPDRNXFixVqODCep0gLFikdMvlJmGzMvvz\n/r8ficaPoosCCQlV5luzUiT3YkasZmFVQArL5P1IxCri+9nbt59Lb52B/4Fi\nwhX9sqnTUZrjp3d3WPUPxHI+TAbq3anFmiwB2c8iwZIZDAxMnATOs5Diwfx7\nsq+GCkCn3Hk0rMGhZfj7LG5AZjkmQme4CuMbfBT4zordQ0H4vl4ptDmXNtC4\nh3s1y0Nfhx0ZXp8Dc0sQh3TlbqahNZbHsgVSYZuqJ+pvpAROfS597JWOiny5\n7hu2QNeLHwUpT+qxs0D1mGH/5TFAE9dRUgI07uTQXB5VRh/JV6uaB934k27M\ned/9s21OgvrRb/Mey64rWcQVd89dHpEbo1YS60d4Yf4oYTEG9eQOu0xd00ei\nAi1z68SdW4uQEWZHUvo2EMharxnB+Bmr3LvwHtdX3u5oG+tneTTb0qI5Tmil\ns+r8OGMmbi4iDdDdpLbPEoguzt/IfX5FCi0YHU+hnMdVssA0rLM4BIMJj7sG\ngaErwViFJ9eb4qMbrktHFpzseyBnWV9MS8eoGb9fsv2J3aLmfbXExcSfHOfD\ntSlIv/7+cHpOoTLRcMPmnrBlKhh1ybX4u8+mpu7HhcELtWeS2INPiOkp6OnT\nkSqF\r\n=GvYt\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDfeXGjvT6oU5KMtuvGJvqMHmyPQpQr9uii0k8kUTSTWAiBSSII04QMmHJ0TGpdU99FeGqZ2fEojhLnE71QTGyVqgQ=="}]},"_npmUser":{"name":"joelmoss","email":"joel@developwithstyle.com"},"directories":{},"maintainers":[{"name":"joelmoss","email":"joel@developwithstyle.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ibiza_1.0.0-beta.7_1637276433179_0.8094998607835051"},"_hasShrinkwrap":false},"1.0.0-beta.8":{"name":"ibiza","author":{"name":"Joel Moss"},"version":"1.0.0-beta.8","description":"React State Management for Party Animals","license":"MIT","homepage":"https://github.com/joelmoss/ibiza","repository":{"type":"git","url":"https://github.com/joelmoss/ibiza.git"},"bugs":{"url":"https://github.com/joelmoss/ibiza/issues"},"keywords":["react","state","proxy"],"source":"index.js","main":"dist/index.cjs","module":"dist/index.js","sideEffects":false,"scripts":{"test":"jest","build":"rollup -c","prepack":"rollup -c","size":"size-limit"},"size-limit":[{"name":"useIbiza","path":"index.js","import":"{ useIbiza }"},{"name":"store","path":"index.js","import":"{ store }"},{"name":"createModel","path":"index.js","import":"{ createModel }"}],"prettier":{"trailingComma":"none","printWidth":100,"semi":false,"singleQuote":true,"arrowParens":"avoid"},"peerDependencies":{"react":">=16"},"devDependencies":{"@babel/core":"^7.16.0","@babel/plugin-transform-runtime":"^7.16.4","@babel/preset-env":"^7.16.4","@babel/preset-react":"^7.16.0","@rollup/plugin-babel":"^5.3.0","@rollup/plugin-node-resolve":"^13.0.6","@size-limit/preset-small-lib":"^7.0.0","@testing-library/jest-dom":"^5.15.0","@testing-library/react":"^12.1.2","@testing-library/react-hooks":"^7.0.2","babel-jest":"^27.3.1","babel-plugin-lodash":"^3.3.4","cross-fetch":"^3.1.4","fetch-mock-jest":"^1.5.1","jest":"^27.3.1","msw":"^0.35.0","parcel":"^2.0.1","react":"^17.0.2","react-dom":"^17.0.2","rollup":"^2.60.0","rollup-plugin-size":"^0.2.2","size-limit":"^7.0.0"},"dependencies":{"@babel/runtime":"^7.16.3","fast-equals":"^2.0.3","lodash":"^4.17.21","micro-memoize":"^4.0.9"},"readmeFilename":"README.md","readme":"# Ibiza - React State Management for Party Animals\n\nIbiza gets out of your way and simply lets you read and write state as you would with regular\nJavascript assignment. It maintains a global state object and is smart enough to know when to\nrerender your components based on state usage and modification.\n\n## How It Works ✨\n\nA component calls the `useIbiza` React hook, which returns the store state as a JS Proxy object.\nThis Proxy records when a state property is accessed or \"used\". Then when that property is mutated,\nthe component is rerendered.\n\nThis means that you can mutate your state in any way, but your component will only rerender if you\nmutate state that you have used.\n\nState can be mutated from anywhere - not just from within a component.\n\nThe following component will rerender when the button is clicked, because `name` has changed.\n\n```jsx\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n      <button onClick={() => void (state.name = 'Joel')}></button>\n    </div>\n  )\n}\n```\n\nThe following component will not rerender when the button is clicked, because even though `age` has\nbeen mutated, it is not actually being used within the component.\n\n```jsx\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n      <button onClick={() => void (state.age = 44)}></button>\n    </div>\n  )\n}\n```\n\n### Initial State\n\nYou can pass some initial state to `useIbiza` which will be merged with existing state in the Ibiza\nstore.\n\n```jsx\nconst App = () => {\n  const state = useIbiza({ user: { name: 'Joel' } })\n\n  return <h1>Hello {state.name}</h1>\n}\n```\n\nThis is safe to include in the body of your component, as it will only be merged into the store on\nfirst render.\n\n### Slicing\n\nIbiza supports deeply nested objects, allowing you to design the shape of your state any way you\nlike. To help you work with such nested state, the `useIbiza` hook supports slicing.\n\nThe following example assumes you have an existing state object:\n\n```javascript\n{\n  user: {\n    name: 'Joel',\n    partner: {\n      name: 'Sam',\n    }\n  }\n}\n```\n\nPass a string to `useIbiza` to fetch a specific slice of state. The string should be the path to the\nobject that you want.\n\n```jsx\nconst App = () => {\n  const partner = useIbiza('user.partner')\n\n  return (\n    <div>\n      <h1>Hello {partner.name}</h1>\n      <button onClick={() => void (partner.name = 'Bob')}></button>\n    </div>\n  )\n}\n```\n\nNote that slicing is really only supported as a convenience, and will not generally help with\nperformance.\n\n### Models\n\nIbiza is at its most powerful when working with models. They provide reusability and flexibility.\n\nCreate a model using the `createModel` helper, where the first argument is the model name, and the\nsecond argument is the initial model state.\n\n```javascript\nexport default createModel('user', {\n  firstName: 'Joel',\n  lastName: 'Moss',\n  children: [{ firstName: 'Ash' }, { firstName: 'Elijah' }, { firstName: 'Eve' }]\n})\n```\n\n`createModel` returns a hook which you can use. You can now import your model anywhere:\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <div>\n      <h1>Hello {user.firstName}</h1>\n      <ul>\n        {user.children.map((child, i) => (\n          <li key={i}>{child.firstName}</li>\n        ))}\n      </ul>\n    </div>\n  )\n}\n```\n\n#### Initial State\n\nSometimes you want to be able to define your model with some initial state that could be provided\ndynamically. For example, from component props or some other parameters.\n\n`createModel` can accept a function as its second argument. This function will be called on\ninitialisation with two arguments; the current `state` and any `props` passed to it when its hook is\nfirst called.\n\n```javascript\nexport default createModel('user', (state, props) => ({\n  firstName: 'Joel',\n  lastName: 'Moss'\n  ...props\n}))\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = ({ yearOfBirth }) => {\n  const user = useModel({ yearOfBirth })\n\n  return (\n    <div>\n      <h1>\n        Hello {user.firstName}, you were born in {user.yearOfBirth}.\n      </h1>\n    </div>\n  )\n}\n```\n\n### Functions\n\nYou can use regular function in your model. They accept the current state as the first argument, and\n`this` will also be the current state (as long as you don't use hash rocket functions).\n\n```jsx\nconst App = () => {\n  const state = useIbiza({\n    count: 0,\n    increment: state => {\n      ++state.count\n    },\n    decrement() {\n      ++this.count\n    }\n  })\n\n  return (\n    <>\n      <h1>Count = {state.count}</h1>\n      <button onClick={state.increment}>Increment</button>\n      <button onClick={state.decrement}>Decrement</button>\n    </>\n  )\n}\n```\n\nWhen reading/writing state within a function, `this` responds to the state at the level where the\nfunction sits. This means that if the function is deeply nested, `this` will not include state lower\ndown.\n\nTo solve this, you can call `this.$model` to access your model, or `this.$root` to access the root\nof the state.\n\n```javascript\nuseIbiza({\n  deepstate: {\n    user: {\n      name: 'Joel',\n      partner: {\n        name: 'Sam',\n\n        get partner() {\n          // `this` refers to 'deepstate.user.partner'.\n          // `this.$model` refers to 'deepstate.user'.\n          // `this.$root` is the whole store state.\n          return this.$model.name\n        }\n      }\n    }\n  }\n})\n```\n\nFunctions accept any number of arguments just like regular functions do.\n\n```jsx\nconst App = () => {\n  const user = useIbiza({\n    children: [],\n    addChild(state, firstName, lastName) {\n      state.children.push({ firstName, lastName }) // or `this.children.push(...)`\n    }\n  })\n\n  return (\n    <>\n      <ul>\n        {user.children.map((child, i) => (\n          <li key={i}>\n            {child.firstName} {child.lastName}\n          </li>\n        ))}\n      </ul>\n      <button onClick={() => user.addChild('Ash', 'Moss')}></button>\n    </>\n  )\n}\n```\n\n### Getters and Setters\n\nIbiza supports Javascript getters and setters in your state and models.\n\n```javascript\nexport default createModel('user', {\n  firstName: 'Joel',\n  lastName: 'Moss',\n\n  get fullName() {\n    // You can read/write to your state via `this`.\n    return `${this.firstName} ${this.lastName}`\n  },\n\n  set fullName(value) {\n    const [firstName, lastName] = value.split(' ')\n\n    this.firstName = firstName\n    this.lastName = lastName\n  }\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <h1>Hello {user.fullName}</h1>\n      <button onClick={() => void (user.fullName = 'Bob Bones')}></button>\n    </>\n  )\n}\n```\n\n### Async Functions\n\nFunctions can be async and/or return Promises, and support React's Suspense by default.\n\n```javascript\nexport default createModel('user', {\n  name: 'Joel',\n\n  async doSomething() {\n    return await someAsyncAction()\n  }\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <h1>Hello {user.fullName}</h1>\n      <button onClick={user.doSomething}></button>\n    </>\n  )\n}\n```\n\n### URL Models\n\nBecause reading and writing to/from the server is so common, Ibiza has support to make this easy\nwith URL Models, similar to react-query. Simply use a valid and relative URL as you model name or\nslice.\n\nThe following will fetch the user from the server at `/user`, suspending the component while it does\nso. The data is fetched only when it does not exist in the store.\n\n```jsx\nconst App = () => {\n  const user = useIbiza('/user')\n\n  return <h1>Hello {user.name}</h1>\n}\n```\n\nYou can safely mutate your model, as all mutations will remain local.\n\nYou can write your model state back to the server. It the server responds with JSON, the model will\nbe updated with that response.\n\n```jsx\nconst App = () => {\n  const user = useIbiza('/user')\n\n  const renameUser = async () => {\n    await user.save({ body: { name: 'Bob' } })\n  }\n\n  return (\n    <>\n      <h1>Hello {user.name}</h1>\n      <button onClick={() => renameUser()}></button>\n    </>\n  )\n}\n```\n\nURL Models can also be defined with `createModel`:\n\n```javascript\nexport default createModel('/user')\n```\n\n`createModel` returns a hook which you can use. You can now import your model anywhere:\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return <h1>Hello {user.firstName}</h1>\n}\n```\n","_id":"ibiza@1.0.0-beta.8","dist":{"shasum":"3658c07104a1ed62d8f9240f04a67693b7846c02","integrity":"sha512-Uz6IvsejqAjQAgk0kHl788PAIBV32EQWWK9ROo/3mHss6h74nHF8kKKe1vyhTgxpAu4FWi13usZhXTpKb46F4w==","tarball":"https://registry.npmjs.org/ibiza/-/ibiza-1.0.0-beta.8.tgz","fileCount":21,"unpackedSize":271873,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhltwQCRA9TVsSAnZWagAAn2QP/3U9Z3+u7EhfTMjI4xRD\nQICcymZcPyil/g50fS5e1SmEMdmRZH/mgA69BXRCj+3iyqcJMxUnOZS+rsHd\n0RbAvwXxkq6J55JTSdgkMB0tJS1JUUtudOAWnRjyYx9RUQD7QeI5z2SfuRMw\nZN5upw4m2VDX/Lvn4YjMR8zmDAuEmTD5JKEPkuYN3Qyrbkv7hneOrpmLYsUY\nmvc9Gpt8UZluYmUNsErwESmTqzi0eLXU5tbfaHQrrh4wg/iGhPvF8ZzhwllJ\nOGYuyUUV2IIjQcLsgB6fQ1Jcy+JcJcqSmsz80PxkgCXDX02rnOrdUF2UhdWN\nAf1ucr4qNbgvZKNbjigbCWNrOs86qKuly18M3ZayoWGzKLvjp0NIn6msffCE\nWVoYvYoexspvkvsChIeSpHcBwyW+qt7Ixc2MnvlenI2BDRDTKtF9ArNVJLvS\n/nWX9WqeXsnFtejcXNRqJBHSHfACvcuK3Vwu+ks8dLkVKcX/c17ng3/4m3v2\nnzm1q4fNg2LEjkFluj72216k5Uv94KEyzvaWy2Cl6YU2BRpDqSZer6iBd3MS\nVDEt8aUQYnGifeLM3Yz3/6tx6U/VrkAVMGE2ijDAaZTHgspiZNC2XK0Qq6y+\n/yTohiO3S4i+gCv3Lx4/qOJMfJnCiCrov5pnJF/4u2dH7sSI2d03q87sVmu0\noZkR\r\n=58QK\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFjzRQhdtxZPlGPWN3minRWnpmPYI0AEao72h4QFf2a8AiEAmHpHmNTYRhnoVJrBTFvcJx88LzhQza6PFfYddEhghIU="}]},"_npmUser":{"name":"joelmoss","email":"joel@developwithstyle.com"},"directories":{},"maintainers":[{"name":"joelmoss","email":"joel@developwithstyle.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ibiza_1.0.0-beta.8_1637276688534_0.9747469027271387"},"_hasShrinkwrap":false},"1.0.0-beta.9":{"name":"ibiza","author":{"name":"Joel Moss"},"version":"1.0.0-beta.9","description":"React State Management for Party Animals","license":"MIT","homepage":"https://github.com/joelmoss/ibiza","repository":{"type":"git","url":"https://github.com/joelmoss/ibiza.git"},"bugs":{"url":"https://github.com/joelmoss/ibiza/issues"},"keywords":["react","state","proxy"],"source":"index.js","main":"dist/index.cjs","module":"dist/index.js","exports":{"require":"./dist/index.cjs","import":"./dist/index.js"},"sideEffects":false,"scripts":{"test":"jest","build":"rollup -c","prepack":"rollup -c","size":"rollup -c && size-limit"},"size-limit":[{"name":"useIbiza","path":"index.js","import":"{ useIbiza }","limit":"1 s"},{"name":"store","path":"index.js","import":"{ store }","limit":"1 s"},{"name":"createModel","path":"index.js","import":"{ createModel }","limit":"1 s"},{"name":"rawStateOf","path":"index.js","import":"{ rawStateOf }","limit":"1 s"},{"name":"createAccessor","path":"index.js","import":"{ createAccessor }","limit":"1 s"},{"name":"freeze","path":"index.js","import":"{ freeze }","limit":"1 s"}],"prettier":{"trailingComma":"none","printWidth":100,"semi":false,"singleQuote":true,"arrowParens":"avoid"},"peerDependencies":{"react":">=16"},"devDependencies":{"@babel/core":"^7.16.0","@babel/plugin-transform-runtime":"^7.16.4","@babel/preset-env":"^7.16.4","@babel/preset-react":"^7.16.0","@rollup/plugin-babel":"^5.3.0","@rollup/plugin-node-resolve":"^13.0.6","@size-limit/preset-big-lib":"^7.0.1","@testing-library/jest-dom":"^5.15.0","@testing-library/react":"^12.1.2","@testing-library/react-hooks":"^7.0.2","babel-jest":"^27.3.1","babel-plugin-lodash":"^3.3.4","cross-fetch":"^3.1.4","fetch-mock-jest":"^1.5.1","jest":"^27.3.1","msw":"^0.35.0","react":"^17.0.2","react-dom":"^17.0.2","rollup":"^2.60.0","rollup-plugin-size":"^0.2.2","size-limit":"^7.0.0"},"dependencies":{"@babel/runtime":"^7.16.3","fast-equals":"^2.0.3","lodash":"^4.17.21","micro-memoize":"^4.0.9"},"readmeFilename":"README.md","readme":"# Ibiza - React State Management for Party Animals\n\nIbiza gets out of your way and simply lets you read and write state as you would with regular\nJavascript assignment. It maintains a global state object and is smart enough to know when to\nrerender your components based on state usage and modification.\n\n## How It Works ✨\n\nA component calls the `useIbiza` React hook, which returns the store state as a JS Proxy object.\nThis Proxy records when a state property is accessed or \"used\". Then when that property is mutated,\nthe component is rerendered.\n\nThis means that you can mutate your state in any way, but your component will only rerender if you\nmutate state that you have used.\n\nState can be mutated from anywhere - not just from within a component.\n\nThe following component will rerender when the button is clicked, because `name` has changed.\n\n```jsx\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n      <button onClick={() => void (state.name = 'Joel')}></button>\n    </div>\n  )\n}\n```\n\nThe following component will not rerender when the button is clicked, because even though `age` has\nbeen mutated, it is not actually being used within the component.\n\n```jsx\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n      <button onClick={() => void (state.age = 44)}></button>\n    </div>\n  )\n}\n```\n\n### Initial State\n\nYou can pass some initial state to `useIbiza` which will be merged with existing state in the Ibiza\nstore.\n\n```jsx\nconst App = () => {\n  const state = useIbiza({ user: { name: 'Joel' } })\n\n  return <h1>Hello {state.name}</h1>\n}\n```\n\nThis is safe to include in the body of your component, as it will only be merged into the store on\nfirst render.\n\n### Slicing\n\nIbiza supports deeply nested objects, allowing you to design the shape of your state any way you\nlike. To help you work with such nested state, the `useIbiza` hook supports slicing.\n\nThe following example assumes you have an existing state object:\n\n```javascript\n{\n  user: {\n    name: 'Joel',\n    partner: {\n      name: 'Sam',\n    }\n  }\n}\n```\n\nPass a string to `useIbiza` to fetch a specific slice of state. The string should be the path to the\nobject that you want.\n\n```jsx\nconst App = () => {\n  const partner = useIbiza('user.partner')\n\n  return (\n    <div>\n      <h1>Hello {partner.name}</h1>\n      <button onClick={() => void (partner.name = 'Bob')}></button>\n    </div>\n  )\n}\n```\n\nNote that slicing is really only supported as a convenience, and will not generally help with\nperformance.\n\n### Models\n\nIbiza is at its most powerful when working with models. They provide reusability and flexibility.\n\nCreate a model using the `createModel` helper, where the first argument is the model name, and the\nsecond argument is the initial model state.\n\n```javascript\nexport default createModel('user', {\n  firstName: 'Joel',\n  lastName: 'Moss',\n  children: [{ firstName: 'Ash' }, { firstName: 'Elijah' }, { firstName: 'Eve' }]\n})\n```\n\n`createModel` returns a hook which you can use. You can now import your model anywhere:\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <div>\n      <h1>Hello {user.firstName}</h1>\n      <ul>\n        {user.children.map((child, i) => (\n          <li key={i}>{child.firstName}</li>\n        ))}\n      </ul>\n    </div>\n  )\n}\n```\n\n#### Initial State\n\nSometimes you want to be able to define your model with some initial state that could be provided\ndynamically. For example, from component props or some other parameters.\n\n`createModel` can accept a function as its second argument. This function will be called on\ninitialisation with two arguments; the current `state` and any `props` passed to it when its hook is\nfirst called.\n\n```javascript\nexport default createModel('user', (state, props) => ({\n  firstName: 'Joel',\n  lastName: 'Moss'\n  ...props\n}))\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = ({ yearOfBirth }) => {\n  const user = useModel({ yearOfBirth })\n\n  return (\n    <div>\n      <h1>\n        Hello {user.firstName}, you were born in {user.yearOfBirth}.\n      </h1>\n    </div>\n  )\n}\n```\n\n### Functions\n\nYou can use regular function in your model. They accept the current state as the first argument, and\n`this` will also be the current state (as long as you don't use hash rocket functions).\n\n```jsx\nconst App = () => {\n  const state = useIbiza({\n    count: 0,\n    increment: state => {\n      ++state.count\n    },\n    decrement() {\n      ++this.count\n    }\n  })\n\n  return (\n    <>\n      <h1>Count = {state.count}</h1>\n      <button onClick={state.increment}>Increment</button>\n      <button onClick={state.decrement}>Decrement</button>\n    </>\n  )\n}\n```\n\nWhen reading/writing state within a function, `this` responds to the state at the level where the\nfunction sits. This means that if the function is deeply nested, `this` will not include state lower\ndown.\n\nTo solve this, you can call `this.$model` to access your model, or `this.$root` to access the root\nof the state.\n\n```javascript\nuseIbiza({\n  deepstate: {\n    user: {\n      name: 'Joel',\n      partner: {\n        name: 'Sam',\n\n        get partner() {\n          // `this` refers to 'deepstate.user.partner'.\n          // `this.$model` refers to 'deepstate.user'.\n          // `this.$root` is the whole store state.\n          return this.$model.name\n        }\n      }\n    }\n  }\n})\n```\n\nFunctions accept any number of arguments just like regular functions do.\n\n```jsx\nconst App = () => {\n  const user = useIbiza({\n    children: [],\n    addChild(state, firstName, lastName) {\n      state.children.push({ firstName, lastName }) // or `this.children.push(...)`\n    }\n  })\n\n  return (\n    <>\n      <ul>\n        {user.children.map((child, i) => (\n          <li key={i}>\n            {child.firstName} {child.lastName}\n          </li>\n        ))}\n      </ul>\n      <button onClick={() => user.addChild('Ash', 'Moss')}></button>\n    </>\n  )\n}\n```\n\n### Getters and Setters\n\nIbiza supports Javascript getters and setters in your state and models.\n\n```javascript\nexport default createModel('user', {\n  firstName: 'Joel',\n  lastName: 'Moss',\n\n  get fullName() {\n    // You can read/write to your state via `this`.\n    return `${this.firstName} ${this.lastName}`\n  },\n\n  set fullName(value) {\n    const [firstName, lastName] = value.split(' ')\n\n    this.firstName = firstName\n    this.lastName = lastName\n  }\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <h1>Hello {user.fullName}</h1>\n      <button onClick={() => void (user.fullName = 'Bob Bones')}></button>\n    </>\n  )\n}\n```\n\n### Async Functions\n\nFunctions can be async and/or return Promises, and support React's Suspense by default.\n\n```javascript\nexport default createModel('user', {\n  name: 'Joel',\n\n  async doSomething() {\n    return await someAsyncAction()\n  }\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <h1>Hello {user.fullName}</h1>\n      <button onClick={user.doSomething}></button>\n    </>\n  )\n}\n```\n\n### URL Models\n\nBecause reading and writing to/from the server is so common, Ibiza has support to make this easy\nwith URL Models, similar to react-query. Simply use a valid and relative URL as you model name or\nslice.\n\nThe following will fetch the user from the server at `/user`, suspending the component while it does\nso. The data is fetched only when it does not exist in the store.\n\n```jsx\nconst App = () => {\n  const user = useIbiza('/user')\n\n  return <h1>Hello {user.name}</h1>\n}\n```\n\nYou can safely mutate your model, as all mutations will remain local.\n\nYou can write your model state back to the server. It the server responds with JSON, the model will\nbe updated with that response.\n\n```jsx\nconst App = () => {\n  const user = useIbiza('/user')\n\n  const renameUser = async () => {\n    await user.save({ body: { name: 'Bob' } })\n  }\n\n  return (\n    <>\n      <h1>Hello {user.name}</h1>\n      <button onClick={() => renameUser()}></button>\n    </>\n  )\n}\n```\n\nURL Models can also be defined with `createModel`:\n\n```javascript\nexport default createModel('/user')\n```\n\n`createModel` returns a hook which you can use. You can now import your model anywhere:\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return <h1>Hello {user.firstName}</h1>\n}\n```\n","_id":"ibiza@1.0.0-beta.9","dist":{"shasum":"d69b43711157a783db7b7fb81205bc8e7726d21d","integrity":"sha512-oAD+iDqBIQvKvbBWKodMEOaS8Dj0YPnLKdLaoa1GZDTfPJysFNrjwy9G++QDU18ZHd1uuGq06Uh7e88L1SjblA==","tarball":"https://registry.npmjs.org/ibiza/-/ibiza-1.0.0-beta.9.tgz","fileCount":21,"unpackedSize":272102,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhlujnCRA9TVsSAnZWagAA24wP/0KL6NIjJ4Ofloncw4fJ\nm1QYx7AdU3tjY2SnCbWqXRmmeAdWtSTKue09OCeGeYc8na3hQDdaX/tV45db\nYS6LLx6/T/QsoYvvtU7YSsAQ9vtTHyc5PIEjLXuE96mAescer7fi69JLasCP\nPHcb72sJZ56VmYBLp0NZzJTE84xJncSL2pUPL1tSJZc4FapXUb1RSc1JWRjY\nlv2VaH4NjJzTubx8+wx7mT1WwwD+IYhdaNiDvkiQvzRe8FszkX0Y22mEJcsQ\ncVWaZ7aPdn23KJrkIRZ7Mz79+xAiBot0xvFV5MpGyZOyvTixkxGusxnLxHIL\nXAwcCQX4CQfcA0WjsRWfXXnazpzjzjParbB4Lt3dUYCDWor0BMQHs3WP/Orh\nVHGpGc6oH3MT+JVFqhitZtZ4klC23pr5KLQi7JBPuWGVPPo3fvZkcbk0N193\nhR+FrQ+67Nd0jme8EIrHXX/KiFZ5qMGfjpxfcekLFXIZiVHuYIeGnIncCWaM\n5jVLTFhChGnk2ITqeQERtsqiGYDXpgXgMA+pswhFh4FbsgkdRWcQvWOTIgEy\necZXGwDwKxb6lrgtSsNjtvKuLSrl92jtVe57vdGwvW+Va07Lffw0d2CF6vtq\n1fTBWWnO4mRNw8W4SJ7RSBZ/ZNzTXHxjcHy0eNY44BCtrnSlHJgBRHpwezUV\nygR1\r\n=TpU2\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCK03dlXGG9GJ7pYtUCF03rOygg+/o3MQkE7P1dujVyCgIgdYiVPppTUmlKDl4Pzj+q9xEGl9FipeoYrm8OJKCEOoI="}]},"_npmUser":{"name":"joelmoss","email":"joel@developwithstyle.com"},"directories":{},"maintainers":[{"name":"joelmoss","email":"joel@developwithstyle.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ibiza_1.0.0-beta.9_1637279974993_0.9955236826922431"},"_hasShrinkwrap":false},"1.0.0":{"name":"ibiza","author":{"name":"Joel Moss"},"version":"1.0.0","description":"React State Management for Party Animals","license":"MIT","homepage":"https://github.com/joelmoss/ibiza","repository":{"type":"git","url":"https://github.com/joelmoss/ibiza.git"},"bugs":{"url":"https://github.com/joelmoss/ibiza/issues"},"keywords":["react","state","proxy"],"source":"index.js","main":"dist/index.cjs","module":"dist/index.js","exports":{"require":"./dist/index.cjs","import":"./dist/index.js"},"sideEffects":false,"scripts":{"test":"jest","build":"rollup -c","prepack":"rollup -c","size":"rollup -c && size-limit"},"size-limit":[{"name":"useIbiza","path":"index.js","import":"{ useIbiza }","limit":"1 s"},{"name":"store","path":"index.js","import":"{ store }","limit":"1 s"},{"name":"createModel","path":"index.js","import":"{ createModel }","limit":"1 s"},{"name":"rawStateOf","path":"index.js","import":"{ rawStateOf }","limit":"1 s"},{"name":"createAccessor","path":"index.js","import":"{ createAccessor }","limit":"1 s"},{"name":"freeze","path":"index.js","import":"{ freeze }","limit":"1 s"}],"prettier":{"trailingComma":"none","printWidth":100,"semi":false,"singleQuote":true,"arrowParens":"avoid"},"peerDependencies":{"react":">=16"},"devDependencies":{"@babel/core":"^7.16.0","@babel/plugin-transform-runtime":"^7.16.4","@babel/preset-env":"^7.16.4","@babel/preset-react":"^7.16.0","@rollup/plugin-babel":"^5.3.0","@rollup/plugin-node-resolve":"^13.0.6","@size-limit/preset-big-lib":"^7.0.1","@testing-library/jest-dom":"^5.15.0","@testing-library/react":"^12.1.2","@testing-library/react-hooks":"^7.0.2","babel-jest":"^27.3.1","babel-plugin-lodash":"^3.3.4","cross-fetch":"^3.1.4","fetch-mock-jest":"^1.5.1","jest":"^27.3.1","msw":"^0.35.0","react":"^17.0.2","react-dom":"^17.0.2","rollup":"^2.60.0","rollup-plugin-size":"^0.2.2","size-limit":"^7.0.0"},"dependencies":{"@babel/runtime":"^7.16.3","fast-equals":"^2.0.3","lodash":"^4.17.21","micro-memoize":"^4.0.9"},"_id":"ibiza@1.0.0","dist":{"shasum":"4517891c74ceb075285cb0c7f26cab973061d52d","integrity":"sha512-84KszHb84KcRxrMDJvPmd1kHUKb6b4DHsxACz6OTZMzSR/BKqr1ZweqyIhlEIIoCI6Q38Oa5K/uK3hHMixRNaQ==","tarball":"https://registry.npmjs.org/ibiza/-/ibiza-1.0.0.tgz","fileCount":21,"unpackedSize":272095,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhnQ/WCRA9TVsSAnZWagAAMpcP/1bIju2BHutjaaxvSVNL\n92LOGOdyy8Y8M3iF8w5uIKrz9nqtb7RZU5Xfuc8yyj9UYvXIQ6u2brSnGmWy\nPYnhiwG1te1sShy9cniSRRDxXQyWPeHFhsKpn+Wc46DwJHxZw4y3SSMTFxa0\njuijE6sfcFvFzAnHLXSDv1uymw0o4zn2XGAyJvK/NDABuXC+jRbORT9CSHsy\npSTqHQ7RWQbO4BpYTVfmRLHxAf9odx67lrUuP4G2h1HwAose6zc6IOQOBjjP\nSLnR7zJaySdEOYHhHMTXEUas8bN2RWSlLtbat3e7F/oP9WeDggW7BP2JC6DW\n4to6EG5tkuzrbHmiz0ei0iXbbsQ4pmWrvp30wT5SKkvk1tArERNCLsctPBEX\nOSsvZX4OyzLWWsipgA0R6qrk8tVlNDwYGfJ5sl05m5Z4pPapy6kwZsI+yC9i\n4niCFnoDh3F/zh2igaior3LXkvDGguajuOa2fprBc8IvSKjhraOASmni8Pgw\n0t5RjIPG2jGWGibZR3re4LX6Vb7l0m22JfYXmDQMd/V2FD0sPFS9zq00U50d\n5AdbzcePet7wNRLsnDssrPYE5sOaKKAewKME/gQZ5kPg4onBtrlpKcHww4EF\n4SdFlQTlD9oZqAZ8GJPEyTua4wdzOBFsrssX0L36IOY3+FbrhTJilLN3v824\niKYE\r\n=P1YI\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCQRixSF9DsBtD1EqBgUKDfRYNBTwjpYuUY/rUGefAE9QIhAIlw00p2HUp/3DWmwKsIPHQCIgnKDR640Ova6O5DkXpK"}]},"_npmUser":{"name":"joelmoss","email":"joel@developwithstyle.com"},"directories":{},"maintainers":[{"name":"joelmoss","email":"joel@developwithstyle.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ibiza_1.0.0_1637683157948_0.02945231349726929"},"_hasShrinkwrap":false},"1.1.0":{"name":"ibiza","author":{"name":"Joel Moss"},"version":"1.1.0","description":"React State Management for Party Animals","license":"MIT","homepage":"https://github.com/joelmoss/ibiza","repository":{"type":"git","url":"https://github.com/joelmoss/ibiza.git"},"bugs":{"url":"https://github.com/joelmoss/ibiza/issues"},"keywords":["react","state","proxy"],"source":"index.js","main":"dist/index.cjs","module":"dist/index.js","exports":{"require":"./dist/index.cjs","import":"./dist/index.js"},"sideEffects":false,"scripts":{"test":"jest","build":"rollup -c","prepack":"rollup -c","size":"rollup -c && size-limit"},"size-limit":[{"name":"useIbiza","path":"index.js","import":"{ useIbiza }","limit":"1 s"},{"name":"store","path":"index.js","import":"{ store }","limit":"1 s"},{"name":"createModel","path":"index.js","import":"{ createModel }","limit":"1 s"},{"name":"rawStateOf","path":"index.js","import":"{ rawStateOf }","limit":"1 s"},{"name":"createAccessor","path":"index.js","import":"{ createAccessor }","limit":"1 s"},{"name":"freeze","path":"index.js","import":"{ freeze }","limit":"1 s"}],"prettier":{"trailingComma":"none","printWidth":100,"semi":false,"singleQuote":true,"arrowParens":"avoid"},"peerDependencies":{"react":">=16"},"devDependencies":{"@babel/core":"^7.16.0","@babel/plugin-transform-runtime":"^7.16.4","@babel/preset-env":"^7.16.4","@babel/preset-react":"^7.16.0","@rollup/plugin-babel":"^5.3.0","@rollup/plugin-node-resolve":"^13.0.6","@size-limit/preset-big-lib":"^7.0.1","@testing-library/jest-dom":"^5.15.0","@testing-library/react":"^12.1.2","@testing-library/react-hooks":"^7.0.2","babel-jest":"^27.3.1","babel-plugin-lodash":"^3.3.4","cross-fetch":"^3.1.4","fetch-mock-jest":"^1.5.1","jest":"^27.3.1","msw":"^0.35.0","react":"^17.0.2","react-dom":"^17.0.2","rollup":"^2.60.0","rollup-plugin-size":"^0.2.2","size-limit":"^7.0.0"},"dependencies":{"@babel/runtime":"^7.16.3","fast-equals":"^2.0.3","lodash":"^4.17.21","micro-memoize":"^4.0.9"},"_id":"ibiza@1.1.0","dist":{"shasum":"920d75791732675fb3c4164b6b847d2fad3efba4","integrity":"sha512-XpCYtPJb3lRwJkoRuklnZSh38gCJRMsfmEfBs+ypwGKKnUUcp+28y0KJ1x94zj9cKB+6GieWYC7FIUMeIDnXHw==","tarball":"https://registry.npmjs.org/ibiza/-/ibiza-1.1.0.tgz","fileCount":21,"unpackedSize":275693,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhpkOrCRA9TVsSAnZWagAAfnsQAIoWpVQOxJ1h0372PyBj\nyNoj20Q9HrvCKuLYM4TtS+j91WCM/QG1pMVoJb9t3WTy9XVh+qo9fwUbRO4r\nVT1JRfEVB1Hg1BFT+JFIiH+HozRQTtEi258kYXOpBItrWKYCWv2COXvwQpyO\nABU1U4/5bY13xmZtvK8ey1DbsAsApo4oQDia5k4SQLejvX9xgBPMaMULm0Yr\nxlwkVgGa861ieul8TxUvUk3e/hODqbRtyiNhlRMX6VW9xZJHKuDWOScLGQzX\n55ptb4c1qMSx47m36uAiaPGZj+c4F2G/b6rDF17yqGXpIIZa88T0t6m1WaI/\nWGIvZ7YYVdqUF8NOjbfRkfJQUP11QA5blGJu7lCRSB217heHytlxJEidnqtg\nEkUCFPKOChgUdE2bE9SbRfZ8C1kJrFLPWKr8qhTofwqB+FIv7K/y/SVZBiII\nM3q9dmHypFdVHyS+LPQeSB5gke6QznYUReXcPj5RK354FlUDLQRcj/rKW2Ww\noXEJvqBW/Ayqljr02myQVpWgG/oQNGZL9tC4T2y4s9BFpgXozz4hpOtF/0/l\nWfc3VzGT3Tr+zhUPQ1sSgQpUmz+0LfLl6+Au0ImgYG0EG7GGn2yMwgFVYxT/\nvjZMY3mq67BGq2Q+5ypRN5QmaMOh5yPnyf0cFE9D5IiCsO6eOdYf9oDrrExJ\nHQvi\r\n=lgPY\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICdMq960FWLhsZ9BQCur1+Q5JHFXv/gthqfJc224dVHHAiApfbl/BjiO2yoNGWTPatol9LV4asoze+uI602P3cUy5g=="}]},"_npmUser":{"name":"joelmoss","email":"joel@developwithstyle.com"},"directories":{},"maintainers":[{"name":"joelmoss","email":"joel@developwithstyle.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ibiza_1.1.0_1638286251804_0.7725944078528717"},"_hasShrinkwrap":false},"1.1.1":{"name":"ibiza","author":{"name":"Joel Moss"},"version":"1.1.1","description":"React State Management for Party Animals","license":"MIT","homepage":"https://github.com/joelmoss/ibiza","repository":{"type":"git","url":"https://github.com/joelmoss/ibiza.git"},"bugs":{"url":"https://github.com/joelmoss/ibiza/issues"},"keywords":["react","state","proxy"],"source":"index.js","main":"dist/index.cjs","module":"dist/index.js","exports":{"require":"./dist/index.cjs","import":"./dist/index.js"},"sideEffects":false,"scripts":{"test":"jest","build":"rollup -c","prepack":"rollup -c","size":"rollup -c && size-limit"},"size-limit":[{"name":"useIbiza","path":"index.js","import":"{ useIbiza }","limit":"1 s"},{"name":"store","path":"index.js","import":"{ store }","limit":"1 s"},{"name":"createModel","path":"index.js","import":"{ createModel }","limit":"1 s"},{"name":"rawStateOf","path":"index.js","import":"{ rawStateOf }","limit":"1 s"},{"name":"createAccessor","path":"index.js","import":"{ createAccessor }","limit":"1 s"},{"name":"freeze","path":"index.js","import":"{ freeze }","limit":"1 s"}],"prettier":{"trailingComma":"none","printWidth":100,"semi":false,"singleQuote":true,"arrowParens":"avoid"},"peerDependencies":{"react":">=16"},"devDependencies":{"@babel/core":"^7.16.0","@babel/plugin-transform-runtime":"^7.16.4","@babel/preset-env":"^7.16.4","@babel/preset-react":"^7.16.0","@rollup/plugin-babel":"^5.3.0","@rollup/plugin-node-resolve":"^13.0.6","@size-limit/preset-big-lib":"^7.0.1","@testing-library/jest-dom":"^5.15.0","@testing-library/react":"^12.1.2","@testing-library/react-hooks":"^7.0.2","babel-jest":"^27.3.1","babel-plugin-lodash":"^3.3.4","cross-fetch":"^3.1.4","fetch-mock-jest":"^1.5.1","jest":"^27.3.1","msw":"^0.35.0","react":"^17.0.2","react-dom":"^17.0.2","rollup":"^2.60.0","rollup-plugin-size":"^0.2.2","size-limit":"^7.0.0"},"dependencies":{"@babel/runtime":"^7.16.3","fast-equals":"^2.0.3","lodash":"^4.17.21","micro-memoize":"^4.0.9"},"_id":"ibiza@1.1.1","dist":{"shasum":"fab4d6acac4e743c76b9fb23d6f26380808f0bd5","integrity":"sha512-GhGjTyrS8ogVsLEqrxoVh8wYYTQGL2iqn2bA1eBJ7KCaT796p9Yp3P1ozx00kumphm8mUrB2wDSdNgGLPPVvXQ==","tarball":"https://registry.npmjs.org/ibiza/-/ibiza-1.1.1.tgz","fileCount":21,"unpackedSize":277566,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh3sZLCRA9TVsSAnZWagAA93oP/RlqwvL2M2XaPVxpvT/Q\n5GahWC7WqoVus25JtyV3MBoEPMZj3jaAuRr5XtvAV13g4HbjySNSP7IYR2mX\nzsa7s6CQbEubleo7WADvIwIqonwlncz7xTtXZQ4sRI6ApdywzZaWm373K3QH\nH/GYixNu6Qys29ZxI495fvyek+AVYwP2gQfWme/cc/ton4FAaUSy5ngdb9wt\nIG5RmBPvstP1mLX4cGkXVVEk5HHuxVrmpO+XJVLFwxdZhfrj0ncghr92qSEN\nPwVK7RQe7Az5OCaB4dmpka0FUz6xXw0foeeIbi3TrxZppvgTpxYWCXUj10UR\n1waPQHeTZGLuM7XUOhSkFA3Bt58qDqYlI1jUVFPp6CKnzNjphH4188M9/KR3\nUzM8n65m2aRkGi/VmGupONSGbrZBHkeulDT7x+H2eFLkSEZAuxZquLxGydT0\nPiVD33OdHyPotsKe9IMdmW1MNRE7HqGz3/wLG9YpmfueZe+EDYLqR62mpfLS\nbI8bX/D6nCNfaiIKbR3VCrT7VU0wCjL3yCkAni6gfIxX5BwmxWicARUQ4w8f\nUQu+FMfNxA2P/tqWtQgm9fipUTDhZik/ZcbdeZcpbELqrVLHVHSUVVNRa8pA\nNNyglM7pgxI1bs6Rwg3P98eWZhu57qaBPjNhXw2hLhmVPIiNvFQidRtBzK7S\nIGCS\r\n=nikl\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDVDrKhxY2MkgjJ2BBkZ2Fuk/IGi3n96zHxKJdPZo/4swIgHpLBPREDkq8g19qVJksI8UPednUB3UcLPbTys7vH7lo="}]},"_npmUser":{"name":"joelmoss","email":"joel@developwithstyle.com"},"directories":{},"maintainers":[{"name":"joelmoss","email":"joel@developwithstyle.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ibiza_1.1.1_1641989707832_0.9552798277808474"},"_hasShrinkwrap":false},"1.1.2":{"name":"ibiza","author":{"name":"Joel Moss"},"version":"1.1.2","description":"React State Management for Party Animals","license":"MIT","homepage":"https://github.com/joelmoss/ibiza","repository":{"type":"git","url":"https://github.com/joelmoss/ibiza.git"},"bugs":{"url":"https://github.com/joelmoss/ibiza/issues"},"keywords":["react","state","proxy"],"source":"index.js","main":"dist/index.cjs","module":"dist/index.js","exports":{"require":"./dist/index.cjs","import":"./dist/index.js"},"sideEffects":false,"scripts":{"test":"jest","build":"rollup -c","prepack":"rollup -c","size":"rollup -c && size-limit"},"size-limit":[{"name":"useIbiza","path":"index.js","import":"{ useIbiza }","limit":"1 s"},{"name":"store","path":"index.js","import":"{ store }","limit":"1 s"},{"name":"createModel","path":"index.js","import":"{ createModel }","limit":"1 s"},{"name":"rawStateOf","path":"index.js","import":"{ rawStateOf }","limit":"1 s"},{"name":"createAccessor","path":"index.js","import":"{ createAccessor }","limit":"1 s"},{"name":"freeze","path":"index.js","import":"{ freeze }","limit":"1 s"}],"prettier":{"trailingComma":"none","printWidth":100,"semi":false,"singleQuote":true,"arrowParens":"avoid"},"peerDependencies":{"react":">=16"},"devDependencies":{"@babel/core":"^7.16.0","@babel/plugin-transform-runtime":"^7.16.4","@babel/preset-env":"^7.16.4","@babel/preset-react":"^7.16.0","@rollup/plugin-babel":"^5.3.0","@rollup/plugin-node-resolve":"^13.0.6","@size-limit/preset-big-lib":"^7.0.1","@testing-library/jest-dom":"^5.15.0","@testing-library/react":"^12.1.2","@testing-library/react-hooks":"^7.0.2","babel-jest":"^27.3.1","babel-plugin-lodash":"^3.3.4","cross-fetch":"^3.1.4","fetch-mock-jest":"^1.5.1","jest":"^27.3.1","msw":"^0.36.0","react":"^17.0.2","react-dom":"^17.0.2","rollup":"^2.60.0","rollup-plugin-size":"^0.2.2","size-limit":"^7.0.0"},"dependencies":{"@babel/runtime":"^7.16.3","fast-equals":"^2.0.3","lodash":"^4.17.21","micro-memoize":"^4.0.9"},"_id":"ibiza@1.1.2","dist":{"shasum":"203055c0b40e00349d4d6bee0207899fd0cbaaa4","integrity":"sha512-a8EMXJ0rqW3pJqBtMX2xzc0io+rLSqCGkxJwfM5tnQ+bKvvSXrWrpsXXD3QIjQL8armPp6PlTCSfIPBR0Tc1+g==","tarball":"https://registry.npmjs.org/ibiza/-/ibiza-1.1.2.tgz","fileCount":21,"unpackedSize":305343,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh+SJ+CRA9TVsSAnZWagAAaAoQAJxXSPU+KsZS737MIBwK\nvwzSmsjiEs+s7Pjp2BGMJX0A/0VWfTF8ceNjg9/cPTY5P/U5WQeKce9mxHE6\nafpMWFoH/atnTr4Hn2duuoZJ0mXiSV3cUxIdx47rbDmuO08YvuJn0cWC/SRU\nOnTnjdbHfybjJhSQxHQCukOf7pU8u0lHQ7obf6cYOtp37MJhndamng2I7bOm\n40W2PLbZdnjR7EkMy9o59sfN/dJY/pOB+Kfd12jLNqvsI4TzKVie4R5Ms/SK\nfIYVJAr6Of9OC81zJX+fq0wN758zHMtPyD4gZ6XWpdDywgl082os6tmnG6EL\nUeYLlLRrXTLIsn4lNZv0dmhMSgrfyKP7+dsvj1dvJzntYM6Jnzy6BlFaF259\nxGKfB01TdhZ0NxQ4kotk1JfNcSbbHUlTjUDaEMOT6Ic2ww8gLXMqKj5sTWe7\nSYIxSopj3WSOL2IGFlL/8RQwmmhrHhII3RJteU9Q0gySk1r9Y13QoaFJrpcu\nhjYEj6DXWUEeBcDz/5wmgu446kzM4s1Jr2byjPJ825CXe+/MJHrmsnKLdEXa\nAaWabIiQhKX/KvA9sYwsscr4iEXdp+GZHldNmxNYwEFkDlbu/6oLiS6SgjD7\npRCazC3m4hdHr4hHDabFS+EG9Z5rCidFOmwax0dypXRWclwxjZ0GtftXYT+z\nByrI\r\n=6r7j\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDGnr4Qii0VWT4luKwR4eihdabgF4SBRWB5t2cp7L/NpgIhAPqxD3zBdkDIRRYPSK1BJJGBu3JHeRyczDFl3IgecBm7"}]},"_npmUser":{"name":"joelmoss","email":"joel@developwithstyle.com"},"directories":{},"maintainers":[{"name":"joelmoss","email":"joel@developwithstyle.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ibiza_1.1.2_1643717246441_0.13876331461343194"},"_hasShrinkwrap":false},"1.1.3":{"name":"ibiza","author":{"name":"Joel Moss"},"version":"1.1.3","description":"React State Management for Party Animals","license":"MIT","homepage":"https://github.com/joelmoss/ibiza","repository":{"type":"git","url":"https://github.com/joelmoss/ibiza.git"},"bugs":{"url":"https://github.com/joelmoss/ibiza/issues"},"keywords":["react","state","proxy"],"type":"module","source":"index.js","main":"dist/ibiza.cjs","module":"dist/ibiza.module.js","unpkg":"dist/ibiza.umd.js","exports":{"require":"./dist/ibiza.cjs","default":"./dist/ibiza.modern.js"},"sideEffects":false,"scripts":{"test":"jest","build":"microbundle","dev":"microbundle watch","size":"microbundle && size-limit"},"size-limit":[{"name":"useIbiza","path":"index.js","import":"{ useIbiza }","limit":"1 s"},{"name":"store","path":"index.js","import":"{ store }","limit":"1 s"},{"name":"createModel","path":"index.js","import":"{ createModel }","limit":"1 s"},{"name":"rawStateOf","path":"index.js","import":"{ rawStateOf }","limit":"1 s"},{"name":"createAccessor","path":"index.js","import":"{ createAccessor }","limit":"1 s"},{"name":"freeze","path":"index.js","import":"{ freeze }","limit":"1 s"}],"prettier":{"trailingComma":"none","printWidth":100,"semi":false,"singleQuote":true,"arrowParens":"avoid"},"peerDependencies":{"react":">=16"},"devDependencies":{"@babel/core":"^7.16.0","@babel/plugin-transform-runtime":"^7.16.4","@babel/preset-env":"^7.16.4","@babel/preset-react":"^7.16.0","@babel/runtime":"^7.16.3","@size-limit/preset-big-lib":"^7.0.1","@testing-library/jest-dom":"^5.15.0","@testing-library/react":"^12.1.2","@testing-library/react-hooks":"^7.0.2","babel-jest":"^27.3.1","cross-fetch":"^3.1.4","fetch-mock-jest":"^1.5.1","jest":"^27.3.1","microbundle":"^0.14.2","msw":"^0.36.0","react":"^17.0.2","react-dom":"^17.0.2","size-limit":"^7.0.0"},"dependencies":{"fast-equals":"^2.0.3","lodash.get":"^4.4.2","lodash.set":"^4.3.2","micro-memoize":"^4.0.9"},"_id":"ibiza@1.1.3","dist":{"shasum":"0be3d3f7e998d6a98e275b52eb6714c62ab23a5a","integrity":"sha512-S7k7hzGknEu+p+ovuR5F/a3bWqBlD5Kd1hYUhTkERGHoMlNHKmYd9DJ/QuYo1Yqxm6Pa3MrnCf3KMr18ZzFGPQ==","tarball":"https://registry.npmjs.org/ibiza/-/ibiza-1.1.3.tgz","fileCount":25,"unpackedSize":327991,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh+pekCRA9TVsSAnZWagAA7jMQAIhSvUhnRiCxGuqvavQ4\n3qvDazKmfldW5wUfj/uxnUfXE1zOo1mVWktv69N/6Cy3gC2fxGoAAOY8q5BH\nWv84jxvv7kepaZuhrMBhkwQr9duHM1BITWJUIc/9gttbDAUKEYLfudpGsKIE\n4daBr9fsvKqgBWy0Nm/brPCEpYPIrK5fOKshU/4vFoJVb/DESxtbkG0WcE2c\nw4xnlmBcAmQrttQwz0vn3fzuoxQWDJjyCkpH64dDKP0LM64z4Hb6kzeRAlrE\nnmHbHBLzG89WKxrgb2BVS1TiAqOTrUottjdhWXv1Q4Wh1IzGgRSINoaiWgQ6\n/dxOqfK8n+jeS+JO8tHiWF7Um8aqOlWpucAvvq/nBOgG/zU/8iGX/XGMUaaE\n8yKm4DigcoySWWjAqgmev8JfSuIw9uwGklpbbPpuUvLbrzqh/rFojFAdYT4m\nmUCipOp2JS9Xe0GS0/dh0ytkeUykDNuArgJNIeQ3IjRBbuB6UTAIPMnxx9wG\njX2pZ75SwrS5YLhB5bCVWL+0jfuUT5rKlVTU/SkDqU2utIi97WCOZPepTSxd\nrgLLZtV5jRkImma3Dywet2mGmxn7c0KpZgfKf3YjeULFTrZ9+K9uNIdsAZbc\nKCT+waqcSSknMY5Wz1AZHPzbhVjdCYbY5NIkQi/PaDjYOFEobTsy1b3RniMe\nAeO8\r\n=/k+F\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCID8RxT5ipa4aR2fPmmRWRkM6QGUkt5yCT9qi1dJpdSylAiEAoHrLYkj/ioDblB8wiHaQQHOL6XdFntH71kOSx47TxvE="}]},"_npmUser":{"name":"joelmoss","email":"joel@developwithstyle.com"},"directories":{},"maintainers":[{"name":"joelmoss","email":"joel@developwithstyle.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ibiza_1.1.3_1643812772249_0.8496214015388917"},"_hasShrinkwrap":false},"1.1.4":{"name":"ibiza","author":{"name":"Joel Moss"},"version":"1.1.4","description":"React State Management for Party Animals","license":"MIT","homepage":"https://github.com/joelmoss/ibiza","repository":{"type":"git","url":"https://github.com/joelmoss/ibiza.git"},"bugs":{"url":"https://github.com/joelmoss/ibiza/issues"},"keywords":["react","state","proxy"],"type":"module","source":"index.js","main":"dist/ibiza.cjs","module":"dist/ibiza.module.js","unpkg":"dist/ibiza.umd.js","exports":{"require":"./dist/ibiza.cjs","default":"./dist/ibiza.modern.js"},"sideEffects":false,"scripts":{"test":"jest","build":"microbundle","dev":"microbundle watch","size":"microbundle && size-limit"},"size-limit":[{"name":"useIbiza","path":"index.js","import":"{ useIbiza }","limit":"1 s"},{"name":"store","path":"index.js","import":"{ store }","limit":"1 s"},{"name":"createModel","path":"index.js","import":"{ createModel }","limit":"1 s"},{"name":"rawStateOf","path":"index.js","import":"{ rawStateOf }","limit":"1 s"},{"name":"createAccessor","path":"index.js","import":"{ createAccessor }","limit":"1 s"},{"name":"freeze","path":"index.js","import":"{ freeze }","limit":"1 s"}],"prettier":{"trailingComma":"none","printWidth":100,"semi":false,"singleQuote":true,"arrowParens":"avoid"},"peerDependencies":{"react":">=16"},"devDependencies":{"@babel/core":"^7.16.0","@babel/plugin-transform-runtime":"^7.16.4","@babel/preset-env":"^7.16.4","@babel/preset-react":"^7.16.0","@babel/runtime":"^7.16.3","@size-limit/preset-big-lib":"^7.0.1","@testing-library/jest-dom":"^5.15.0","@testing-library/react":"^12.1.2","@testing-library/react-hooks":"^7.0.2","babel-jest":"^27.3.1","cross-fetch":"^3.1.4","fetch-mock-jest":"^1.5.1","jest":"^27.3.1","microbundle":"^0.14.2","msw":"^0.36.0","react":"^17.0.2","react-dom":"^17.0.2","size-limit":"^7.0.0"},"dependencies":{"fast-equals":"^2.0.3","micro-memoize":"^4.0.9"},"_id":"ibiza@1.1.4","dist":{"shasum":"7c195f6df0b1b692e36d28fd52615f6c51c05be5","integrity":"sha512-OuuPI2VmoUpryX4mqvgtXRok9lJM1exmninFb1f8GebwnbJOMReuM59Iiy/biGQa4/Nu5RjfQAv84lfVYerPfg==","tarball":"https://registry.npmjs.org/ibiza/-/ibiza-1.1.4.tgz","fileCount":26,"unpackedSize":383139,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh+v5OCRA9TVsSAnZWagAAceAQAICFlQWv40VfdkzIatrq\nV0tXS1gJDWDaxtIlNMuRjTCB7ctJLJ+2cXRGLrMi1RnVuCAJQseMVeHIjtPP\nBrl/ZOgl+jIr/lKsmeNFzpUozRqh6ywMyBV527u7hjjnGvBUNX73CtvndZ9O\nBCKAC8XLtX/pAcZZJG1TgvA4oUFazZsvIw/Nvn0RHCSObo9A5DYcKDoi6No3\n5iCkWGJV+uRU9vGaRbFYeYPKnnUfnh2JxslxVVjLcDZJBKbRjpiy1jkCwYEO\n80qGbvCOzycSQNRc8E4s16snjXLhwZ5Wj8m+8TAKv9dch0ApqhlVSZFqfVLV\nONmR/EtElDJUspHYqn048evQXUl52kvwnv/e3KFtZNzNectK9JrLVp9br7jh\nac7Fy36aJYIFsVvaIplO46yIiCvVOkijmcH8MN2bOhsU8mTw6nBEkaSx3x9Q\nid19vQLWUdPKpd/nV17nZehynBGjNjh3JAYBjJOZiyetS6+IIid53cXpQXUt\nawGsoaML3DeMb8oclzfxTusIUYkFtyBhShZ4/AwSbs/psQID14amckL6Qa+z\nQlxkr+1X7Rww7uNXmhKdKtIqZX3O4UhTrjKuxbkC/YeEEBwrSFxaEJTByok8\nJ2se+6Cs5y36YOA80f0LPSYm0xss87UIRenNUETQcPDwcEjH6bgBjfSYZbIn\nys/8\r\n=BUvq\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIF/vDwjDzMukwb0JnwGQszp7dTEVgAWjfsQUt7U0Mc8zAiBWkU2h82ACjXmclwCho8Qh5FZZxQCJaLptz0XOlgw1Lw=="}]},"_npmUser":{"name":"joelmoss","email":"joel@developwithstyle.com"},"directories":{},"maintainers":[{"name":"joelmoss","email":"joel@developwithstyle.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ibiza_1.1.4_1643839054405_0.2433160010852078"},"_hasShrinkwrap":false},"1.1.5":{"name":"ibiza","author":{"name":"Joel Moss"},"version":"1.1.5","description":"React State Management for Party Animals","license":"MIT","homepage":"https://github.com/joelmoss/ibiza","repository":{"type":"git","url":"https://github.com/joelmoss/ibiza.git"},"bugs":{"url":"https://github.com/joelmoss/ibiza/issues"},"keywords":["react","state","proxy"],"type":"module","source":"index.js","main":"dist/ibiza.cjs","module":"dist/ibiza.module.js","unpkg":"dist/ibiza.umd.js","exports":{"require":"./dist/ibiza.cjs","default":"./dist/ibiza.modern.js"},"sideEffects":false,"scripts":{"test":"jest","build":"microbundle","dev":"microbundle watch","size":"microbundle && size-limit"},"size-limit":[{"name":"useIbiza","path":"index.js","import":"{ useIbiza }","limit":"1 s"},{"name":"store","path":"index.js","import":"{ store }","limit":"1 s"},{"name":"createModel","path":"index.js","import":"{ createModel }","limit":"1 s"},{"name":"rawStateOf","path":"index.js","import":"{ rawStateOf }","limit":"1 s"},{"name":"createAccessor","path":"index.js","import":"{ createAccessor }","limit":"1 s"},{"name":"freeze","path":"index.js","import":"{ freeze }","limit":"1 s"}],"prettier":{"trailingComma":"none","printWidth":100,"semi":false,"singleQuote":true,"arrowParens":"avoid"},"peerDependencies":{"react":">=16"},"devDependencies":{"@babel/core":"^7.16.0","@babel/plugin-transform-runtime":"^7.16.4","@babel/preset-env":"^7.16.4","@babel/preset-react":"^7.16.0","@babel/runtime":"^7.16.3","@size-limit/preset-big-lib":"^7.0.1","@testing-library/jest-dom":"^5.15.0","@testing-library/react":"^12.1.2","@testing-library/react-hooks":"^7.0.2","babel-jest":"^27.3.1","cross-fetch":"^3.1.4","fetch-mock-jest":"^1.5.1","jest":"^27.3.1","microbundle":"^0.14.2","msw":"^0.36.0","react":"^17.0.2","react-dom":"^17.0.2","size-limit":"^7.0.0"},"dependencies":{"fast-equals":"^2.0.3","micro-memoize":"^4.0.9"},"_id":"ibiza@1.1.5","dist":{"shasum":"192d390e0ff5ff160836794f6e382e8498d69466","integrity":"sha512-E6fdUgEj6HDosKVSG050SkCKXLnmDzHHbprL81fHTuv5gXcryQa0QfwrSlmTw+2TIk34UCpbmS85Bzt4DYtJpQ==","tarball":"https://registry.npmjs.org/ibiza/-/ibiza-1.1.5.tgz","fileCount":26,"unpackedSize":384807,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJiBDklCRA9TVsSAnZWagAAp7gP/iojbWpEd1+aCFBdRLRl\nppjuUALYZcAAd+S/Ijor5uskdwpnkqULHCLpevON7GJ53tvkcKLq0Tazussj\ni0VYru3LeLKXfwmPIf7/y/Ik1uS/Sqox6MUFqjmofetAgHFmHgnC7zT2Cp85\nVj3IhVII/0hgeWhSZ/8IXXOITrtxKYYXN1702bTl6+rZvXw6lMHB15hYhGMv\nAyDZCMtKUy6ZUDffmLo1G+m3nkoErq36x0YmraHF8Ivzoq3rPsOav3TlfF0Q\nms6s8ppzeZDQN/scBP1HR/MvUe9UG9jgpf2barnclPmF9Y/mm7XFEZgsglgf\ndwkfJIxxA8DXbQysPWeethHE/9v7vmB7usn0QIntDrlgHqja+SXg3tKCoKgz\nAtEhhtdxMdSGPyuGO4Z5YwvnA5UsxyMS1w1mBhtiH+88GwKkLLT0Uto9cOl7\nqwIFecp8ZNjzzv9KMfMt8fTihJwrXazC5HVoT/eoN9qNeFZIB6jr5XRW6DQ7\nV131IdP6DTKicyYMIs9oDobjGYWRAWiEqhaiQx5mzLQVU3jAbjG5J0lldAdE\n+m108vXk6oFPHk/CiB1gwtZ7UoqKiBEG98rvJgJyzAS1wIKe1aPUNAK+RtVx\nxtUdDnnP5zfK0kRsrBnR2Xi8yyhVm0edQRB8arwwyBJEeNZKj2q0r4OBEy+v\ntj5F\r\n=3uOH\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD4/U1mQteiLT6ofOBqOd4Z0d4yv9+L4gEB5f1uw/JZcQIgCQCDoo4w7qjZB1aEcMjmyu+rNgMmRGz1p8bWKFJKXlo="}]},"_npmUser":{"name":"joelmoss","email":"joel@developwithstyle.com"},"directories":{},"maintainers":[{"name":"joelmoss","email":"joel@developwithstyle.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ibiza_1.1.5_1644443941267_0.8370347779307936"},"_hasShrinkwrap":false},"1.2.0":{"name":"ibiza","author":{"name":"Joel Moss"},"version":"1.2.0","description":"React State Management for Party Animals","license":"MIT","homepage":"https://github.com/joelmoss/ibiza","repository":{"type":"git","url":"https://github.com/joelmoss/ibiza.git"},"bugs":{"url":"https://github.com/joelmoss/ibiza/issues"},"keywords":["react","state","proxy"],"type":"module","source":"index.js","main":"dist/ibiza.cjs","module":"dist/ibiza.module.js","unpkg":"dist/ibiza.umd.js","exports":{"development":"./index.js","require":"./dist/ibiza.cjs","default":"./dist/ibiza.modern.js"},"sideEffects":false,"scripts":{"test":"jest","build":"microbundle","dev":"microbundle watch","size":"microbundle && size-limit"},"size-limit":[{"name":"useIbiza","path":"index.js","import":"{ useIbiza }","limit":"1 s"},{"name":"store","path":"index.js","import":"{ store }","limit":"1 s"},{"name":"createModel","path":"index.js","import":"{ createModel }","limit":"1 s"},{"name":"rawStateOf","path":"index.js","import":"{ rawStateOf }","limit":"1 s"},{"name":"createAccessor","path":"index.js","import":"{ createAccessor }","limit":"1 s"},{"name":"freeze","path":"index.js","import":"{ freeze }","limit":"1 s"}],"prettier":{"trailingComma":"none","printWidth":100,"semi":false,"singleQuote":true,"arrowParens":"avoid"},"peerDependencies":{"react":">=16"},"devDependencies":{"@babel/core":"^7.16.0","@babel/plugin-transform-runtime":"^7.16.4","@babel/preset-env":"^7.16.4","@babel/preset-react":"^7.16.0","@babel/runtime":"^7.16.3","@size-limit/preset-big-lib":"^7.0.1","@testing-library/jest-dom":"^5.15.0","@testing-library/react":"^12.1.2","@testing-library/react-hooks":"^7.0.2","babel-jest":"^27.3.1","cross-fetch":"^3.1.4","fetch-mock-jest":"^1.5.1","jest":"^27.3.1","microbundle":"^0.14.2","msw":"^0.36.0","react":"^17.0.2","react-dom":"^17.0.2","size-limit":"^7.0.0"},"dependencies":{"fast-equals":"^2.0.3","micro-memoize":"^4.0.9"},"_id":"ibiza@1.2.0","dist":{"shasum":"bc21d86eea9d658fc8f15d813f465d2a5cc5ea96","integrity":"sha512-EwW5XbvO5giGhwbb+G0tnlwZ2pfvRF5rVsm0J8l58egzR0LVV3tgzxnae5WheWTkduUTgxbhbki/qkBBagbT2A==","tarball":"https://registry.npmjs.org/ibiza/-/ibiza-1.2.0.tgz","fileCount":26,"unpackedSize":393192,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiD3smACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqG7w/+MfVHdW5Eu+6MgZqLmrsaKM9r/FlL77NVxGML79SmAosMrJ1D\r\ny0xnaYaRETomrxOfu97XCYk/jtPo5pNwKzL5oXQZlrOETQj2whKwLOBLJtiC\r\n+jPQ9Pfl84BYBXJoHcbJm/sCnwLDmZcx6ZgEKEOKAd4a3PuSYNEoeYr6gIY1\r\nycvIcN/HsvKd88lioZF4q9dCAztNTSrQm9aCObJDQdlH/DcokBGltI9bX69A\r\nEQ6Dal5sVIDprkiuERnDV3pyDorD9fjtTa57xClZy23aMQ6I6IL96WJADW+Z\r\nRGj/qcM/Mbp4u3Bqq+cSssVeGPjBkAK9uqyMGpnKE96aVsqCTg8EIwSqYIPq\r\nvn7uKanLtBVEAVO3m7PYogR/lrSEpTRym9iQ4lCM19prQvEKa1V84CC9zX3c\r\n51wJWxJP/79IaY35210E/36lM63u9rGvHB5b3cRl2Cea6/OwZXQ/w2e4kg5X\r\njP1EtiBp7wn6+nAeIK5OUnMxtBpIlLVzx3SCSg7yHbDHww2PUgWljZ64SLlR\r\n615EeN9+ksZ0zwBFP4jXXIita1ffZH/L3mQuJg6mA1G1whYqW5rMHA/SzWb7\r\n6Ni0THr/JLSOKxzuv57V/iRZEhVl2b0uVnGJDhAgvXDfuTzBf5cQ5e2bJshb\r\nWywoGiHNeLg8o+g6jTx/mOpx35WvD2O/Kv4=\r\n=wSRD\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCVhsMmz6wrz8wuOZF7AjpkNNxVog/1Au7kbhGdYLIgBgIgcNWmyk/xVH5Fci16Rk0Qj/cb1CUgiRBgSs+FqWAMf1M="}]},"_npmUser":{"name":"joelmoss","email":"joel@developwithstyle.com"},"directories":{},"maintainers":[{"name":"joelmoss","email":"joel@developwithstyle.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ibiza_1.2.0_1645181734830_0.10346075418192413"},"_hasShrinkwrap":false},"1.3.0-0":{"name":"ibiza","author":{"name":"Joel Moss"},"version":"1.3.0-0","description":"React State Management for Party Animals","license":"MIT","homepage":"https://github.com/joelmoss/ibiza","repository":{"type":"git","url":"https://github.com/joelmoss/ibiza.git"},"bugs":{"url":"https://github.com/joelmoss/ibiza/issues"},"keywords":["react","state","proxy"],"type":"module","source":"src/index.js","main":"dist/ibiza.cjs","module":"dist/ibiza.module.js","unpkg":"dist/ibiza.umd.js","exports":{"require":"./dist/ibiza.cjs","default":"./dist/ibiza.modern.js"},"sideEffects":false,"scripts":{"clean":"rimraf dist","test":"jest","build":"microbundle","dev":"microbundle watch","prepublishOnly":"yarn clean && yarn build","size":"microbundle && size-limit"},"size-limit":[{"name":"useIbiza","path":"./src/index.js","import":"{ useIbiza }","limit":"1 s"},{"name":"store","path":"./src/index.js","import":"{ store }","limit":"1 s"},{"name":"createModel","path":"./src/index.js","import":"{ createModel }","limit":"1 s"},{"name":"rawStateOf","path":"./src/index.js","import":"{ rawStateOf }","limit":"1 s"},{"name":"createAccessor","path":"./src/index.js","import":"{ createAccessor }","limit":"1 s"},{"name":"freeze","path":"./src/index.js","import":"{ freeze }","limit":"1 s"}],"prettier":{"trailingComma":"none","printWidth":100,"semi":false,"singleQuote":true,"arrowParens":"avoid"},"peerDependencies":{"react":">=16"},"devDependencies":{"@size-limit/preset-big-lib":"^7.0.1","@swc/core":"^1.2.144","@swc/jest":"^0.2.17","@testing-library/jest-dom":"^5.15.0","@testing-library/react":"^12.1.2","@testing-library/react-hooks":"^7.0.2","cross-fetch":"^3.1.4","fetch-mock-jest":"^1.5.1","ibiza":"link:./ibiza","jest":"^27.3.1","microbundle":"^0.14.2","msw":"^0.36.0","react":"^17.0.2","react-dom":"^17.0.2","rimraf":"^3.0.2","size-limit":"^7.0.0"},"dependencies":{"fast-equals":"^2.0.3","micro-memoize":"^4.0.9"},"readmeFilename":"README.md","readme":"# Ibiza - React State Management for Party Animals\n\nIbiza gets out of your way and simply lets you read and write state as you would with regular\nJavascript assignment. It maintains a global state object and is smart enough to know when to\nrerender your components based on state usage and modification.\n\n## `useIbiza()` ✨\n\nA component calls the `useIbiza` React hook, which returns the store state as a JS Proxy object.\nThis Proxy records when a state property is accessed or \"used\". Then when that property is mutated,\nthe component is rerendered.\n\nThis means that you can mutate your state in any way, but your component will only rerender if you\nmutate state that you have used.\n\nThe following component will rerender when the button is clicked, because `name` has changed.\n\n```jsx\nimport { useIbiza } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n      <button onClick={() => void (state.name = 'Joel')}></button>\n    </div>\n  )\n}\n```\n\nThe following component will not rerender when the button is clicked, because even though `age` has\nbeen mutated, it is not actually being used within the component.\n\n```jsx\nimport { useIbiza } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n      <button onClick={() => void (state.age = 44)}></button>\n    </div>\n  )\n}\n```\n\nState can be mutated from anywhere - not just from within a component:\n\n```js\nimport { useIbiza, store } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n    </div>\n  )\n}\n\n// <App> component will re-render when this line executes, as `name` has changed.\nstore.state.name = 'Ash'\n```\n\n### Initial State\n\nYou can pass some initial state to `useIbiza` which will be merged with existing state in the Ibiza\nstore.\n\n```jsx\nconst App = () => {\n  const state = useIbiza({ user: { name: 'Joel' } })\n\n  return <h1>Hello {state.user.name}</h1>\n}\n```\n\nThis is safe to include in the body of your component, as it will only be merged into the store on\nfirst render.\n\n### Slicing\n\nIbiza supports deeply nested objects, allowing you to design the shape of your state any way you\nlike. To help you work with such nested state, the `useIbiza` hook supports slicing.\n\nThe following example assumes you have an existing state object:\n\n```javascript\n{\n  user: {\n    name: 'Joel',\n    partner: {\n      name: 'Sam',\n    }\n  }\n}\n```\n\nPass a string to `useIbiza` to fetch a specific slice of state. The string should be the path to the\nobject that you want.\n\n```jsx\nconst App = () => {\n  const partner = useIbiza('user.partner')\n\n  return (\n    <div>\n      <h1>Hello {partner.name}</h1>\n      <button onClick={() => void (partner.name = 'Bob')}></button>\n    </div>\n  )\n}\n```\n\nNote that slicing is really only supported as a convenience, and will not generally help with\nperformance.\n\n## `createModel()`\n\nIbiza is at its most powerful when working with models. They provide reusability and flexibility.\n\nCreate a model using the `createModel` helper, where the first argument is the model name, and the\nsecond argument is the initial model state as a plain object.\n\n```javascript\n// model.js\n\nexport default createModel('user', {\n  firstName: 'Joel',\n  lastName: 'Moss',\n  children: [{ firstName: 'Ash' }, { firstName: 'Elijah' }, { firstName: 'Eve' }]\n})\n```\n\n`createModel` returns a hook which you can use. You can now import your model anywhere:\n\n```jsx\n// app.jsx\n\nimport useModel from './model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <div>\n      <h1>Hello {user.firstName}</h1>\n      <ul>\n        {user.children.map((child, i) => (\n          <li key={i}>{child.firstName}</li>\n        ))}\n      </ul>\n    </div>\n  )\n}\n```\n\n### Initial State\n\nSometimes you want to be able to define your model with some initial state that could be provided\ndynamically. For example, from component props or some other parameters.\n\n`createModel` can accept a function as its second argument. This function will be called on\ninitialisation with two arguments; the current `state` and any `props` passed to it when its hook is\nfirst called.\n\n```javascript\n// model.js\n\nexport default createModel('user', (state, props) => ({\n  firstName: 'Joel',\n  lastName: 'Moss'\n  ...props\n}))\n```\n\n```jsx\n// app.jsx\n\nimport useModel from './model'\n\nconst App = ({ yearOfBirth }) => {\n  const user = useModel({ yearOfBirth })\n\n  return (\n    <div>\n      <h1>\n        Hello {user.firstName}, you were born in {user.yearOfBirth}.\n      </h1>\n    </div>\n  )\n}\n```\n\n### Functions\n\nYou can use regular function in your model. They accept the current state as the first argument, and\n`this` will also be the current state (as long as you don't use hash rocket functions).\n\n```jsx\nconst App = () => {\n  const state = useIbiza({\n    count: 0,\n    increment: state => {\n      ++state.count\n    },\n    decrement() {\n      ++this.count\n    }\n  })\n\n  return (\n    <>\n      <h1>Count = {state.count}</h1>\n      <button onClick={state.increment}>Increment</button>\n      <button onClick={state.decrement}>Decrement</button>\n    </>\n  )\n}\n```\n\nWhen reading/writing state within a function, `this` responds to the state at the level where the\nfunction sits. This means that if the function is deeply nested, `this` will not include state lower\ndown.\n\nTo solve this, you can call `this.$model` to access your model, or `this.$root` to access the root\nof the store state.\n\n```javascript\nuseIbiza({\n  deepstate: {\n    user: {\n      name: 'Joel',\n      partner: {\n        name: 'Sam',\n\n        get partner() {\n          // `this` refers to 'deepstate.user.partner'.\n          // `this.$model` refers to 'deepstate.user'.\n          // `this.$root` is the whole store state.\n          return this.$model.name\n        }\n      }\n    }\n  }\n})\n```\n\nFunctions accept any number of arguments just like regular functions do, but don't forget that the\nfirst argument is always the state.\n\n```jsx\nconst App = () => {\n  const user = useIbiza({\n    children: [],\n    addChild(state, firstName, lastName) {\n      state.children.push({ firstName, lastName }) // or `this.children.push(...)`\n    }\n  })\n\n  return (\n    <>\n      <ul>\n        {user.children.map((child, i) => (\n          <li key={i}>\n            {child.firstName} {child.lastName}\n          </li>\n        ))}\n      </ul>\n      <button onClick={() => user.addChild('Ash', 'Moss')}></button>\n    </>\n  )\n}\n```\n\n### Getters and Setters\n\nIbiza supports Javascript getters and setters in your state and models.\n\n```javascript\nexport default createModel('user', {\n  firstName: 'Joel',\n  lastName: 'Moss',\n\n  get fullName() {\n    // You can read/write to your state via `this`.\n    return `${this.firstName} ${this.lastName}`\n  },\n\n  set fullName(value) {\n    const [firstName, lastName] = value.split(' ')\n\n    this.firstName = firstName\n    this.lastName = lastName\n  }\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <h1>Hello {user.fullName}</h1>\n      <button onClick={() => void (user.fullName = 'Bob Bones')}></button>\n    </>\n  )\n}\n```\n\n### Async Functions\n\nFunctions can be async and/or return Promises, and support React's Suspense by default.\n\n```javascript\nexport default createModel('user', {\n  name: 'Joel',\n\n  async doSomething() {\n    return await someAsyncAction()\n  }\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <h1>Hello {user.fullName}</h1>\n      <button onClick={user.doSomething}></button>\n    </>\n  )\n}\n```\n\n### URL Models\n\nBecause reading and writing to/from the server is so common, Ibiza has support to make this easy\nwith URL Models, similar to react-query. Simply use a valid and relative URL as your model name or\nslice.\n\nThe following will fetch the user from the server at `/user`, suspending the component while it does\nso. The data is fetched only when it does not exist in the store.\n\n```jsx\nconst App = () => {\n  const user = useIbiza('/user')\n\n  return <h1>Hello {user.name}</h1>\n}\n```\n\nYou can safely mutate your model, as all mutations will remain local.\n\nYou can write your model state back to the server. It the server responds with JSON, the model will\nbe updated with that response.\n\n```jsx\nconst App = () => {\n  const user = useIbiza('/user')\n\n  const renameUser = async () => {\n    await user.save({ body: { name: 'Bob' } })\n  }\n\n  return (\n    <>\n      <h1>Hello {user.name}</h1>\n      <button onClick={renameUser}></button>\n    </>\n  )\n}\n```\n\nURL Models can also be defined with `createModel`, and accept the same arguments:\n\n```javascript\nexport default createModel('/user')\n```\n\n`createModel` returns a hook which you can use. You can now import your model anywhere:\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return <h1>Hello {user.firstName}</h1>\n}\n```\n\nAdditionally, URL models accept a `fetcher` option, which when provided, will be used as the fetch\nfunction for the model:\n\n```javascript\nexport default createModel('/user', {}, { fetcher: myFetchFunction })\n```\n","_id":"ibiza@1.3.0-0","dist":{"shasum":"766dd069812540ed8443e13034459fc2491173e1","integrity":"sha512-9/+HwCkfexYw6SimrhBWFa0tD+1X12wd+mIxoD1Fm38KX9QPCHA3+vb/1/eNBCo+nCwd+32VcmTHm9dB01heNQ==","tarball":"https://registry.npmjs.org/ibiza/-/ibiza-1.3.0-0.tgz","fileCount":12,"unpackedSize":286998,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiFY0fACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqmuBAAhnWotGOA4OLG205D4hmtLUmRxFPtWS6QxpARrS0IpBw38e92\r\nt+QT5Xrf6lHUEtPaj7+D2tRAl4MctBwYVwxmsoTnenLQrbuRvBwsY3YRovzF\r\n7AuArtw0gcnMZZ3PXZLMtPih3VmgBohq60AlrzbwxsMPJ71vztPQzlD8S/EN\r\n7I3uwRnnBIpRCHB2L0sbeXu3qABtst2Q7wWIHVjluTHveNV38G7s9xBJ0sX9\r\nzQSt7loCiOHQ3wT3Tnpd5X60wZUck4K+ITsLGGwjIk8wx28uscJl3gX9ZI3z\r\n20YAAR+jsXWAlsJ89E18zMZuiIgN0SyMpIvG2W9Y/vif+mSHm/90E6Mq46jj\r\nOsPQZpQjh0sNjWyBPPLQ4pz0J0n2xQoRO2ivT4bfS/TpDPaXXDdHR2bV4Dll\r\nkh14qSHcDqg+9AbCrm1LDcB54SNsmvi5p+pWL0ahQ6lV/yuDa5QvYWOVzUkM\r\nDCdyHfSw49B9TohlbSH3wZ13QLIlGvn0gvXMVQEVhDnsb6R1pi75lP1XX0mE\r\nVSbnjRsJ5MSL6HTVFDgyXXvq92IYwsatEAVpNlb4o5TrTK1GtO7EGHhLAyfV\r\nBz9RUXfOmmP6bQxpkNBP5y5VC1ZpXlIppfgQeWqydCvleO6ZNj1ExdEW34Bn\r\nHIcaJPD//2mXLTDcMiAku2yWHQi1l0iFFxQ=\r\n=JuZc\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIE/FmwGupuMdC4Hs3cz/pkVKsA0Xg9zu1ctSAdV8FVr2AiEA1b6ThWpX/vhYC6KSyN6MNCielDssPK2i9ERZZpT74jQ="}]},"_npmUser":{"name":"joelmoss","email":"joel@developwithstyle.com"},"directories":{},"maintainers":[{"name":"joelmoss","email":"joel@developwithstyle.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ibiza_1.3.0-0_1645579551190_0.38429347435930583"},"_hasShrinkwrap":false},"1.3.1":{"name":"ibiza","author":{"name":"Joel Moss"},"version":"1.3.1","description":"React State Management for Party Animals","license":"MIT","homepage":"https://github.com/joelmoss/ibiza","repository":{"type":"git","url":"https://github.com/joelmoss/ibiza.git"},"bugs":{"url":"https://github.com/joelmoss/ibiza/issues"},"keywords":["react","state","proxy"],"type":"module","source":"src/index.js","main":"dist/ibiza.cjs","module":"dist/ibiza.module.js","unpkg":"dist/ibiza.umd.js","exports":{"require":"./dist/ibiza.cjs","default":"./dist/ibiza.modern.js"},"sideEffects":false,"scripts":{"clean":"rimraf dist","test":"jest","build":"microbundle","dev":"microbundle watch","prepublishOnly":"yarn clean && yarn build","size":"microbundle && size-limit"},"size-limit":[{"name":"useIbiza","path":"./src/index.js","import":"{ useIbiza }","limit":"1 s"},{"name":"store","path":"./src/index.js","import":"{ store }","limit":"1 s"},{"name":"createModel","path":"./src/index.js","import":"{ createModel }","limit":"1 s"},{"name":"rawStateOf","path":"./src/index.js","import":"{ rawStateOf }","limit":"1 s"},{"name":"createAccessor","path":"./src/index.js","import":"{ createAccessor }","limit":"1 s"},{"name":"freeze","path":"./src/index.js","import":"{ freeze }","limit":"1 s"}],"prettier":{"trailingComma":"none","printWidth":100,"semi":false,"singleQuote":true,"arrowParens":"avoid"},"peerDependencies":{"react":">=16"},"devDependencies":{"@size-limit/preset-big-lib":"^7.0.1","@swc/core":"^1.2.144","@swc/jest":"^0.2.17","@testing-library/jest-dom":"^5.15.0","@testing-library/react":"^12.1.2","@testing-library/react-hooks":"^7.0.2","cross-fetch":"^3.1.4","fetch-mock-jest":"^1.5.1","ibiza":"link:./ibiza","jest":"^27.3.1","microbundle":"^0.14.2","msw":"^0.36.0","react":"^17.0.2","react-dom":"^17.0.2","rimraf":"^3.0.2","size-limit":"^7.0.0"},"dependencies":{"fast-equals":"^2.0.3","micro-memoize":"^4.0.9"},"_id":"ibiza@1.3.1","dist":{"shasum":"f3b056b9148723838306b561c0fe11ed117da384","integrity":"sha512-IHwFipzexx1e+XfVV2cSxROsknvIzTKEorLpbp/YaaXGdC6SZSd2iZHKlKSMhV4fim2tE5N2sjjGfaCX6jJdJw==","tarball":"https://registry.npmjs.org/ibiza/-/ibiza-1.3.1.tgz","fileCount":12,"unpackedSize":286996,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiGJ2bACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmq+Aw/+NEpmFp/mpfEz9O0pR4chw8ZAfKCQzT0/L1f9hD6+N3LbCIGa\r\n4kg/JgpAmGw3vfZdfb5QfZ4eq8YUr2ilbgQb2DAwZ7+qiUpTBlcZ2Lcpbi0p\r\nHlLNR8ylQWNSbeZIL/XsT6W2vCMWFs3HO3kPdbbHTo13zild0EyePi7tWspB\r\nc9nYwQ30rk/iDpgQSIMAhWc2Pja94cVZzLaT0wZLFclr46w9mj/JzrVzPW28\r\nZjEqOydbDXtSBivK6wsGPH0nEnr5x8lKcI4fWJaA6NUxEAZrYKrHUBdcrpcI\r\n6Pt4NNjhknGp3FRODlkklmCaNoRu6Ry2oCDa8SHQhF+iEy0BpY0MbWta0f/e\r\nIJb2YM6BpZqW0viv+ZJzVcmtYJ4vFD5ZV70Dwu6sMssKkgN9oquHIAvEPMvA\r\nrkhdc6+ECQK/7YdchG/ppu9pPeZEMLBzSroXmujzl3qKeUODq5+fEcolNa6q\r\nnpDY4dp4mSqjDZ0487AGloOpq5Q+c24nM5YJPXneT4U3WIMKMyuu5MjY6mEn\r\n684PXiEA5DYR+xWqlu3bJ2LJmyt9nkz0gOrn0CoOdkQCGdrJhhY0HKRxblc0\r\nKYc6HnAFe5QpOQHR4ChJlXStrvWC7ullbvXMofFbJ4ktNddU/Y2Wp/zFm7uP\r\nVW/iWZiBbJY++s4Ri07g2ZlzuF5tQtsXwA0=\r\n=DpCR\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDAmPf+ImggJVeFy+bVSCoRVYz72zv8oH5uixepVwbFFAIgYkbR1ZHZyA1jyvEQbCqddP7JbQmuIFMsoaGiQMP1wBc="}]},"_npmUser":{"name":"joelmoss","email":"joel@developwithstyle.com"},"directories":{},"maintainers":[{"name":"joelmoss","email":"joel@developwithstyle.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ibiza_1.3.1_1645780378951_0.8377595968508236"},"_hasShrinkwrap":false},"1.3.2":{"name":"ibiza","author":{"name":"Joel Moss"},"version":"1.3.2","description":"React State Management for Party Animals","license":"MIT","homepage":"https://github.com/joelmoss/ibiza","repository":{"type":"git","url":"https://github.com/joelmoss/ibiza.git"},"bugs":{"url":"https://github.com/joelmoss/ibiza/issues"},"keywords":["react","state","proxy"],"type":"module","source":"src/index.js","main":"dist/ibiza.cjs","module":"dist/ibiza.module.js","unpkg":"dist/ibiza.umd.js","exports":{"require":"./dist/ibiza.cjs","default":"./dist/ibiza.modern.js"},"sideEffects":false,"scripts":{"clean":"rimraf dist","test":"jest","build":"microbundle","dev":"microbundle watch","prepublishOnly":"yarn clean && yarn build","size":"microbundle && size-limit"},"size-limit":[{"name":"useIbiza","path":"./src/index.js","import":"{ useIbiza }","limit":"1 s"},{"name":"store","path":"./src/index.js","import":"{ store }","limit":"1 s"},{"name":"createModel","path":"./src/index.js","import":"{ createModel }","limit":"1 s"},{"name":"rawStateOf","path":"./src/index.js","import":"{ rawStateOf }","limit":"1 s"},{"name":"createAccessor","path":"./src/index.js","import":"{ createAccessor }","limit":"1 s"},{"name":"freeze","path":"./src/index.js","import":"{ freeze }","limit":"1 s"}],"prettier":{"trailingComma":"none","printWidth":100,"semi":false,"singleQuote":true,"arrowParens":"avoid"},"peerDependencies":{"react":">=16"},"devDependencies":{"@size-limit/preset-big-lib":"^7.0.1","@swc/core":"^1.2.144","@swc/jest":"^0.2.17","@testing-library/jest-dom":"^5.15.0","@testing-library/react":"^12.1.2","@testing-library/react-hooks":"^7.0.2","cross-fetch":"^3.1.4","fetch-mock-jest":"^1.5.1","ibiza":"link:./ibiza","jest":"^27.3.1","microbundle":"^0.14.2","msw":"^0.36.0","react":"^17.0.2","react-dom":"^17.0.2","rimraf":"^3.0.2","size-limit":"^7.0.0"},"dependencies":{"fast-equals":"^2.0.3","micro-memoize":"^4.0.9"},"_id":"ibiza@1.3.2","dist":{"shasum":"0a5df36b4a025df3fe4d18d618703bdcbe2c0301","integrity":"sha512-j0LNQMlhlheN7JgFLuwdv0Svh04al7vevb7l+BXZfEQPRsnfOZJnflvkhRldc1K6YNcfG3iLFzaIafPi536Hcw==","tarball":"https://registry.npmjs.org/ibiza/-/ibiza-1.3.2.tgz","fileCount":12,"unpackedSize":286595,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDbczAULyzcqV44ADpvUDR4HRmvjWKsMf+Ooe+EuZzYLAIgVCVshh1zcdosUesytHajndT5+aNXL4u4+lqWTmf+OcA="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJijOe8ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrdhQ//YY8GGnyu2Zx082WYCxbM5xGj24c6jKEnRhxqH0wVNATs7E36\r\nTxUdiLuSOuC2XKIdIf8m8yGKILfZ4Jcm1iJb/FMq99yjnt1je56s2yK5tN4H\r\nPFdUVYDselhabpMXhaW7fRk+RAe2faT0d8Wp6t4CHMW+dJILgGG/e1IamSPK\r\nb5ugpChOfsY7ltEuMKzNiHbEd31RNMtWHhYS0xrEVwMvIMjl73ifoKVqp9tC\r\nvt4qKalw4i9Py3kIDnzwdPajvKMIbhJDuG63OJAS+tgaDVKdBbXWCqQHzDer\r\n/9wkH4I1B6o9ZoILFJVMzi7mT1A/eNMIOGOW9QcqK3fXkTRTYxIdh3ZDjz5d\r\nXJ3XFN13j/LKJYtuRkcACvnWgL1OLopVLmZSeBB82hpspMBLQczEx66g/HPX\r\nQs+jT/1aEHxI9ODflz0N0/1FM6RnJD74rkkC6OThY6FoB7m1Gc1fyX4rkc2n\r\nBtudzvIZhoRodpAVrZjw6udsid0FoEpz4wPQESbmzKQgcEZgIse85blxJLih\r\nnvwXiqFdSskMYypXtTsYd1SbY+g9KXbb1YzEvTnnPUpcCt4K3XmnWf4auIsc\r\nbHQ8su9TeLD/FVNFmqRzRs1G0LppvwFhLZ+Txj062zTFG7lH3v38UX0pxHRZ\r\nwq0kvWwiVxhu5gq8bq3fFAoWTBevHNKhO9Q=\r\n=3Aoy\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"joelmoss","email":"joel@developwithstyle.com"},"directories":{},"maintainers":[{"name":"joelmoss","email":"joel@developwithstyle.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ibiza_1.3.2_1653401532838_0.5292959062818512"},"_hasShrinkwrap":false},"1.4.0":{"name":"ibiza","author":{"name":"Joel Moss"},"version":"1.4.0","description":"React State Management for Party Animals","license":"MIT","homepage":"https://github.com/joelmoss/ibiza","repository":{"type":"git","url":"https://github.com/joelmoss/ibiza.git"},"bugs":{"url":"https://github.com/joelmoss/ibiza/issues"},"keywords":["react","state","proxy"],"type":"module","source":"src/index.js","main":"dist/ibiza.cjs","module":"dist/ibiza.module.js","unpkg":"dist/ibiza.umd.js","exports":{"require":"./dist/ibiza.cjs","default":"./dist/ibiza.modern.js"},"sideEffects":false,"scripts":{"clean":"rimraf dist","test":"jest","build":"microbundle --jsx React.createElement","dev":"microbundle watch --jsx React.createElement","prepublishOnly":"yarn clean && yarn build","size":"microbundle && size-limit"},"size-limit":[{"name":"useIbiza","path":"./src/index.js","import":"{ useIbiza }","limit":"1 s"},{"name":"store","path":"./src/index.js","import":"{ store }","limit":"1 s"},{"name":"createModel","path":"./src/index.js","import":"{ createModel }","limit":"1 s"},{"name":"rawStateOf","path":"./src/index.js","import":"{ rawStateOf }","limit":"1 s"},{"name":"createAccessor","path":"./src/index.js","import":"{ createAccessor }","limit":"1 s"},{"name":"freeze","path":"./src/index.js","import":"{ freeze }","limit":"1 s"}],"prettier":{"trailingComma":"none","printWidth":100,"semi":false,"singleQuote":true,"arrowParens":"avoid"},"peerDependencies":{"react":">=16"},"devDependencies":{"@size-limit/preset-big-lib":"^7.0.1","@swc/core":"^1.2.144","@swc/jest":"^0.2.17","@testing-library/jest-dom":"^5.15.0","@testing-library/react":"^12.1.2","@testing-library/react-hooks":"^7.0.2","cross-fetch":"^3.1.4","fetch-mock-jest":"^1.5.1","ibiza":"link:./ibiza","jest":"^27.3.1","microbundle":"^0.14.2","msw":"^0.36.0","react":"^17.0.2","react-dom":"^17.0.2","rimraf":"^3.0.2","size-limit":"^7.0.0"},"dependencies":{"fast-equals":"^2.0.3","micro-memoize":"^4.0.9"},"_id":"ibiza@1.4.0","dist":{"shasum":"0aa98d663d0d6d977fd8ed7131d65a5654947430","integrity":"sha512-crTM2i3ZBRL4hY9t4M7Ngr8BjQnz9Jo0H/BliQTCl8vdBzMdWa5O5D0aG5nuYtiSCtUBRhGIetc6wsCJ0dwQ5w==","tarball":"https://registry.npmjs.org/ibiza/-/ibiza-1.4.0.tgz","fileCount":12,"unpackedSize":296671,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCY9lcO4SASZE+k0MlUgR16yJMCZiy2XOjn7tO2zwmsDwIgPdPE5TiunKBLvV1ECe8qbScLuJq4CAMkPK0eBfChu3M="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJikBS/ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrWaQ/9HQ6vZph0uN3/9P3gzedu6FLqA2wGotJkGN2foLQytpQlOKeD\r\nOKCu9LsXykEe3ZVah57a4Cr8KRZX+Z1AUrq1omHi8mMKW0bXfyZIW1fYdbfO\r\n95BVj4NpzpKMP/W7qqpDEyW5pfrD2G9Lh9j0oo6ZkRyatgxKpnbmhpioE1zb\r\n8QCRCGi7GiHKJojOIJAwoEvxFa7a3QEOWIDP/+m/LVtCzZSnPhRSAKb+yzEc\r\nbadNZJEkP6v5mRUY2jQX1F/nr5aLFtZ5HMvWbA22TpAd50YDfTvClU89VjbV\r\nT+R/8k3bPnTVtMHm4oU2nezCBdsXLhukETLg7bVAySy6V3d9/RhFIOC69rqa\r\nWjk8on565lqSJZhOC43kh78W9kQPQ4bwAwtTkyCIYPZDj9Fs4hEfGsTn1UY0\r\nwsi2eJnR6ipI4PalgeTS1KbJBw501qSecbiUjgUNMSR/WT+IOOq0leeNAtDj\r\nv4ohWF98EMZ9+5OuHntj+y2ePs4LrD+FmwtAuBXTaJX7/bkY5hJh6I6EjNhs\r\nLXYiH77tejmH2qY9KoOBAbWcFF7qBu4A294jNa+gi6uc9ygIeIWAF5VdWF6w\r\n2eO0rae3aiaSsXdi7fJrcecR2Ua5rH3VcJzIwlRtuo+M/i5pJHGIybhy8A5J\r\nzUBe84cK1zK/7GNgdwKWvi4Q8VRqrCoSn34=\r\n=wlP3\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"joelmoss","email":"joel@developwithstyle.com"},"directories":{},"maintainers":[{"name":"joelmoss","email":"joel@developwithstyle.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ibiza_1.4.0_1653609663499_0.08175778059434768"},"_hasShrinkwrap":false},"1.5.0":{"name":"ibiza","author":{"name":"Joel Moss"},"version":"1.5.0","description":"React State Management for Party Animals","license":"MIT","homepage":"https://github.com/joelmoss/ibiza","repository":{"type":"git","url":"https://github.com/joelmoss/ibiza.git"},"bugs":{"url":"https://github.com/joelmoss/ibiza/issues"},"keywords":["react","state","proxy"],"type":"module","source":"src/index.js","main":"dist/ibiza.cjs","module":"dist/ibiza.module.js","unpkg":"dist/ibiza.umd.js","exports":{"require":"./dist/ibiza.cjs","default":"./dist/ibiza.modern.js"},"sideEffects":false,"scripts":{"clean":"rimraf dist","test":"jest","build":"microbundle --jsx React.createElement","dev":"microbundle watch --jsx React.createElement","prepublishOnly":"yarn clean && yarn build","size":"microbundle && size-limit"},"size-limit":[{"name":"useIbiza","path":"./src/index.js","import":"{ useIbiza }","limit":"1 s"},{"name":"store","path":"./src/index.js","import":"{ store }","limit":"1 s"},{"name":"createModel","path":"./src/index.js","import":"{ createModel }","limit":"1 s"},{"name":"rawStateOf","path":"./src/index.js","import":"{ rawStateOf }","limit":"1 s"},{"name":"createAccessor","path":"./src/index.js","import":"{ createAccessor }","limit":"1 s"},{"name":"freeze","path":"./src/index.js","import":"{ freeze }","limit":"1 s"}],"prettier":{"trailingComma":"none","printWidth":100,"semi":false,"singleQuote":true,"arrowParens":"avoid"},"peerDependencies":{"react":">=16"},"devDependencies":{"@size-limit/preset-big-lib":"^7.0.1","@swc/core":"^1.2.144","@swc/jest":"^0.2.17","@testing-library/jest-dom":"^5.15.0","@testing-library/react":"^12.1.2","@testing-library/react-hooks":"^7.0.2","cross-fetch":"^3.1.4","fetch-mock-jest":"^1.5.1","ibiza":"link:./ibiza","jest":"^27.3.1","microbundle":"^0.14.2","msw":"^0.36.0","react":"^17.0.2","react-dom":"^17.0.2","rimraf":"^3.0.2","size-limit":"^7.0.0"},"dependencies":{"fast-equals":"^2.0.3","micro-memoize":"^4.0.9"},"readmeFilename":"README.md","readme":"# Ibiza - React State Management for Party Animals\n\nIbiza gets out of your way and simply lets you read and write state as you would with regular\nJavascript assignment. It maintains a global state object and is smart enough to know when to\nrerender your components based on state usage and modification.\n\n## `useIbiza()` ✨\n\nA component calls the `useIbiza` React hook, which returns the store state as a JS Proxy object.\nThis Proxy records when a state property is accessed or \"used\". Then when that property is mutated,\nthe component is rerendered.\n\nThis means that you can mutate your state in any way, but your component will only rerender if you\nmutate state that you have used.\n\nThe following component will rerender when the button is clicked, because `name` has changed.\n\n```jsx\nimport { useIbiza } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n      <button onClick={() => void (state.name = 'Joel')}></button>\n    </div>\n  )\n}\n```\n\nThe following component will not rerender when the button is clicked, because even though `age` has\nbeen mutated, it is not actually being used within the component.\n\n```jsx\nimport { useIbiza } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n      <button onClick={() => void (state.age = 44)}></button>\n    </div>\n  )\n}\n```\n\nState can be mutated from anywhere - not just from within a component:\n\n```js\nimport { useIbiza, store } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n    </div>\n  )\n}\n\n// <App> component will re-render when this line executes, as `name` has changed.\nstore.state.name = 'Ash'\n```\n\n### Initial State\n\nYou can pass some initial state to `useIbiza` which will be merged with existing state in the Ibiza\nstore.\n\n```jsx\nconst App = () => {\n  const state = useIbiza({ user: { name: 'Joel' } })\n\n  return <h1>Hello {state.user.name}</h1>\n}\n```\n\nThis is safe to include in the body of your component, as it will only be merged into the store on\nfirst render.\n\n### Slicing\n\nIbiza supports deeply nested objects, allowing you to design the shape of your state any way you\nlike. To help you work with such nested state, the `useIbiza` hook supports slicing.\n\nThe following example assumes you have an existing state object:\n\n```javascript\n{\n  user: {\n    name: 'Joel',\n    partner: {\n      name: 'Sam',\n    }\n  }\n}\n```\n\nPass a string to `useIbiza` to fetch a specific slice of state. The string should be the path to the\nobject that you want.\n\n```jsx\nconst App = () => {\n  const partner = useIbiza('user.partner')\n\n  return (\n    <div>\n      <h1>Hello {partner.name}</h1>\n      <button onClick={() => void (partner.name = 'Bob')}></button>\n    </div>\n  )\n}\n```\n\nNote that slicing is really only supported as a convenience, and will not generally help with\nperformance.\n\n## `createModel()`\n\nIbiza is at its most powerful when working with models. They provide reusability and flexibility.\n\nCreate a model using the `createModel` helper, where the first argument is the model name, and the\nsecond argument is the initial model state as a plain object.\n\n```javascript\n// model.js\n\nexport default createModel('user', {\n  firstName: 'Joel',\n  lastName: 'Moss',\n  children: [{ firstName: 'Ash' }, { firstName: 'Elijah' }, { firstName: 'Eve' }]\n})\n```\n\n`createModel` returns a hook which you can use. You can now import your model anywhere:\n\n```jsx\n// app.jsx\n\nimport useModel from './model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <div>\n      <h1>Hello {user.firstName}</h1>\n      <ul>\n        {user.children.map((child, i) => (\n          <li key={i}>{child.firstName}</li>\n        ))}\n      </ul>\n    </div>\n  )\n}\n```\n\n### Initial State\n\nSometimes you want to be able to define your model with some initial state that could be provided\ndynamically. For example, from component props or some other parameters.\n\n`createModel` can accept a function as its second argument. This function will be called on\ninitialisation with two arguments; the current `state` and any `props` passed to it when its hook is\nfirst called.\n\n```javascript\n// model.js\n\nexport default createModel('user', (state, props) => ({\n  firstName: 'Joel',\n  lastName: 'Moss'\n  ...props\n}))\n```\n\n```jsx\n// app.jsx\n\nimport useModel from './model'\n\nconst App = ({ yearOfBirth }) => {\n  const user = useModel({ yearOfBirth })\n\n  return (\n    <div>\n      <h1>\n        Hello {user.firstName}, you were born in {user.yearOfBirth}.\n      </h1>\n    </div>\n  )\n}\n```\n\n### Functions\n\nYou can use regular function in your model. They accept the current state as the first argument, and\n`this` will also be the current state (as long as you don't use hash rocket functions).\n\n```jsx\nconst App = () => {\n  const state = useIbiza({\n    count: 0,\n    increment: state => {\n      ++state.count\n    },\n    decrement() {\n      ++this.count\n    }\n  })\n\n  return (\n    <>\n      <h1>Count = {state.count}</h1>\n      <button onClick={state.increment}>Increment</button>\n      <button onClick={state.decrement}>Decrement</button>\n    </>\n  )\n}\n```\n\nWhen reading/writing state within a function, `this` responds to the state at the level where the\nfunction sits. This means that if the function is deeply nested, `this` will not include state lower\ndown.\n\nTo solve this, you can call `this.$model` to access your model, or `this.$root` to access the root\nof the store state.\n\n```javascript\nuseIbiza({\n  deepstate: {\n    user: {\n      name: 'Joel',\n      partner: {\n        name: 'Sam',\n\n        get partner() {\n          // `this` refers to 'deepstate.user.partner'.\n          // `this.$model` refers to 'deepstate.user'.\n          // `this.$root` is the whole store state.\n          return this.$model.name\n        }\n      }\n    }\n  }\n})\n```\n\nFunctions accept any number of arguments just like regular functions do, but don't forget that the\nfirst argument is always the state.\n\n```jsx\nconst App = () => {\n  const user = useIbiza({\n    children: [],\n    addChild(state, firstName, lastName) {\n      state.children.push({ firstName, lastName }) // or `this.children.push(...)`\n    }\n  })\n\n  return (\n    <>\n      <ul>\n        {user.children.map((child, i) => (\n          <li key={i}>\n            {child.firstName} {child.lastName}\n          </li>\n        ))}\n      </ul>\n      <button onClick={() => user.addChild('Ash', 'Moss')}></button>\n    </>\n  )\n}\n```\n\n### Getters and Setters\n\nIbiza supports Javascript getters and setters in your state and models.\n\n```javascript\nexport default createModel('user', {\n  firstName: 'Joel',\n  lastName: 'Moss',\n\n  get fullName() {\n    // You can read/write to your state via `this`.\n    return `${this.firstName} ${this.lastName}`\n  },\n\n  set fullName(value) {\n    const [firstName, lastName] = value.split(' ')\n\n    this.firstName = firstName\n    this.lastName = lastName\n  }\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <h1>Hello {user.fullName}</h1>\n      <button onClick={() => void (user.fullName = 'Bob Bones')}></button>\n    </>\n  )\n}\n```\n\n### Async Functions\n\nFunctions can be async and/or return Promises, and support React's Suspense by default.\n\n```javascript\nexport default createModel('user', {\n  name: 'Joel',\n\n  async doSomething() {\n    return await someAsyncAction()\n  }\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <h1>Hello {user.fullName}</h1>\n      <button onClick={user.doSomething}></button>\n    </>\n  )\n}\n```\n\n### URL Models\n\nBecause reading and writing to/from the server is so common, Ibiza has support to make this easy\nwith URL Models, similar to react-query. Simply use a valid and relative URL as your model name or\nslice.\n\nThe following will fetch the user from the server at `/user`, suspending the component while it does\nso. The data is fetched only when it does not exist in the store.\n\n```jsx\nconst App = () => {\n  const user = useIbiza('/user')\n\n  return <h1>Hello {user.name}</h1>\n}\n```\n\nYou can safely mutate your model, as all mutations will remain local.\n\nYou can write your model state back to the server. It the server responds with JSON, the model will\nbe updated with that response.\n\n```jsx\nconst App = () => {\n  const user = useIbiza('/user')\n\n  const renameUser = async () => {\n    await user.save({ body: { name: 'Bob' } })\n  }\n\n  return (\n    <>\n      <h1>Hello {user.name}</h1>\n      <button onClick={renameUser}></button>\n    </>\n  )\n}\n```\n\nURL Models can also be defined with `createModel`, and accept the same arguments:\n\n```javascript\nexport default createModel('/user')\n```\n\n`createModel` returns a hook which you can use. You can now import your model anywhere:\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return <h1>Hello {user.firstName}</h1>\n}\n```\n\nAdditionally, URL models accept a `fetcher` option, which when provided, will be used as the fetch\nfunction for the model:\n\n```javascript\nexport default createModel('/user', {}, { fetcher: myFetchFunction })\n```\n\n## `createContextModel()`\n\nWrap your component in the `IbizaProvider` higher order component, and instead of `createModel()`,\ncreate your model with `createContextModel()` function. The model will automatically be given a\nunique name specific to the wrapped components in IbizaProvider. Just pass the model definition as\nthe first argument. It accepts the same options as `createModel()` for the second argument.\n\n```jsx\nconst useModel = createContextModel(() => ({\n  // Your model definition...\n  name: 'Awesome!'\n}))\n\nconst App = () => {\n  return (\n    <IbizaProvider>\n      <MyComponent />\n    </IbizaProvider>\n  );\n};\n\nconst MyComponent = () => {\n  const model = useModel()\n\n  return <h1>My model is {model.name}</h1>\n};\n```\n\nEach instance of IbizaProvider will use its own state.\n\n```jsx\nconst useFirstModel = createContextModel(() => ({\n  name: 'FIRST!'\n}))\n\nconst useSecondModel = createContextModel(() => ({\n  name: 'SECOND!'\n}))\n\nconst App = () => {\n  return (\n    <>\n      <IbizaProvider>\n        <MyFirstComponent />\n      </IbizaProvider>\n      <IbizaProvider>\n        <MySecondComponent />\n      </IbizaProvider>\n    </>\n  );\n};\n\nconst MyFirstComponent = () => {\n  const model = useFirstModel();\n\n  return <h1>My model is {model.name}</h1>; // My model is FIRST!\n};\n\nconst MySecondComponent = () => {\n  const model = useSecondModel()\n\n  return <h1>My model is {model.name}</h1> // My model is SECOND!\n};\n```\n\n","_id":"ibiza@1.5.0","dist":{"shasum":"378244340217e408921f912a52c7456d5000d42b","integrity":"sha512-M1sCDaEW96Le+3C+hPrYs06iZONKa8cC8f07D3wJKZcaDxVIuF4BixqKwSBk6i7SltFpXFfnM13jjGICGGkGCQ==","tarball":"https://registry.npmjs.org/ibiza/-/ibiza-1.5.0.tgz","fileCount":12,"unpackedSize":298380,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIH5P4xIKydQMbsPdCXlu4TuMq9z//mzG9GY37zShWxHEAiBJqdZc5iq9IFykmIFyyn1u5tHSRByqIHGV9h1jywWQ2g=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJin3XMACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmpo8Q/9ENQgRwMSb5agLwffnr6fVbN4NQGTmf4k6ZkJPpbIDCri5gON\r\nTF35A92RDRGs1R6uxw+Wbz0bx+zU/w6XQR6QiMICir+OIA/VuUPQ24pRbt69\r\nL2nX8CfKB9qNrEw24BuUfcX0avjriKObYpwUNQHzeJxmtfWsjPYjAqgyXaa+\r\nv26TPOAo0eA0GkDcF1XMxhhLbotFCXeHgrSPsT8RGQmuGq17NrBSs9pmtmWw\r\nf98o4SO089pD2VOzCdbhzSYu7es91LFgP4uevwiAksPQ2PutZblw+3lOftP/\r\nkIyCdRaGucl8oWk55LyYAmwnSbO9sxhH8T3dnh5pQoexfV2153q9Lmxa41qL\r\nth1FRiqwcj03gUaqLy1x6KOEpRxOrnk+OZik0nMfKJxHfxgs4Dma7Uq+awIU\r\nCAJkksTxHee22C3O9eNrIEsAQmqQROgKIaiworhI3a665591g+UjkXJoviea\r\nz6bVZJaRM0IDZjeuvvrgVDjQMhasCZaiFiV+J22JOIhKonFRQmFh6Kl8GqCc\r\nq5bSZsaNxG86LEFUYxB955rhgRIj/CFBTMQ8+xefz7nzgdSRYnF9l+tlCgfr\r\nk2kYtncnMgMcLw/8oKvTFZdgWvVbElcLkc17R0O9TlvhrBI+Z8VgdgNaUkcX\r\nSh4nLsJ1CeRcqnPc3ApWqczyqKGOIVtxfhM=\r\n=b4lt\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"joelmoss","email":"joel@developwithstyle.com"},"directories":{},"maintainers":[{"name":"joelmoss","email":"joel@developwithstyle.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ibiza_1.5.0_1654617548687_0.28727161200456575"},"_hasShrinkwrap":false},"1.5.1":{"name":"ibiza","author":{"name":"Joel Moss"},"version":"1.5.1","description":"React State Management for Party Animals","license":"MIT","homepage":"https://github.com/joelmoss/ibiza","repository":{"type":"git","url":"https://github.com/joelmoss/ibiza.git"},"bugs":{"url":"https://github.com/joelmoss/ibiza/issues"},"keywords":["react","state","proxy"],"type":"module","source":"src/index.js","main":"dist/ibiza.cjs","module":"dist/ibiza.module.js","unpkg":"dist/ibiza.umd.js","exports":{"require":"./dist/ibiza.cjs","default":"./dist/ibiza.modern.js"},"sideEffects":false,"scripts":{"clean":"rimraf dist","test":"jest","build":"microbundle --jsx React.createElement","dev":"microbundle watch --jsx React.createElement","prepublishOnly":"yarn clean && yarn build","size":"microbundle && size-limit"},"size-limit":[{"name":"useIbiza","path":"./src/index.js","import":"{ useIbiza }","limit":"1 s"},{"name":"store","path":"./src/index.js","import":"{ store }","limit":"1 s"},{"name":"createModel","path":"./src/index.js","import":"{ createModel }","limit":"1 s"},{"name":"rawStateOf","path":"./src/index.js","import":"{ rawStateOf }","limit":"1 s"},{"name":"createAccessor","path":"./src/index.js","import":"{ createAccessor }","limit":"1 s"},{"name":"freeze","path":"./src/index.js","import":"{ freeze }","limit":"1 s"}],"prettier":{"trailingComma":"none","printWidth":100,"semi":false,"singleQuote":true,"arrowParens":"avoid"},"peerDependencies":{"react":">=16"},"devDependencies":{"@size-limit/preset-big-lib":"^7.0.1","@swc/core":"^1.2.144","@swc/jest":"^0.2.17","@testing-library/jest-dom":"^5.15.0","@testing-library/react":"^12.1.2","@testing-library/react-hooks":"^7.0.2","cross-fetch":"^3.1.4","fetch-mock-jest":"^1.5.1","ibiza":"link:./ibiza","jest":"^27.3.1","microbundle":"^0.14.2","msw":"^0.36.0","react":"^17.0.2","react-dom":"^17.0.2","rimraf":"^3.0.2","size-limit":"^7.0.0"},"dependencies":{"fast-equals":"^2.0.3","micro-memoize":"^4.0.9"},"readmeFilename":"README.md","readme":"# Ibiza - React State Management for Party Animals\n\nIbiza gets out of your way and simply lets you read and write state as you would with regular\nJavascript assignment. It maintains a global state object and is smart enough to know when to\nrerender your components based on state usage and modification.\n\n## `useIbiza()` ✨\n\nA component calls the `useIbiza` React hook, which returns the store state as a JS Proxy object.\nThis Proxy records when a state property is accessed or \"used\". Then when that property is mutated,\nthe component is rerendered.\n\nThis means that you can mutate your state in any way, but your component will only rerender if you\nmutate state that you have used.\n\nThe following component will rerender when the button is clicked, because `name` has changed.\n\n```jsx\nimport { useIbiza } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n      <button onClick={() => void (state.name = 'Joel')}></button>\n    </div>\n  )\n}\n```\n\nThe following component will not rerender when the button is clicked, because even though `age` has\nbeen mutated, it is not actually being used within the component.\n\n```jsx\nimport { useIbiza } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n      <button onClick={() => void (state.age = 44)}></button>\n    </div>\n  )\n}\n```\n\nState can be mutated from anywhere - not just from within a component:\n\n```js\nimport { useIbiza, store } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n    </div>\n  )\n}\n\n// <App> component will re-render when this line executes, as `name` has changed.\nstore.state.name = 'Ash'\n```\n\n### Initial State\n\nYou can pass some initial state to `useIbiza` which will be merged with existing state in the Ibiza\nstore.\n\n```jsx\nconst App = () => {\n  const state = useIbiza({ user: { name: 'Joel' } })\n\n  return <h1>Hello {state.user.name}</h1>\n}\n```\n\nThis is safe to include in the body of your component, as it will only be merged into the store on\nfirst render.\n\n### Slicing\n\nIbiza supports deeply nested objects, allowing you to design the shape of your state any way you\nlike. To help you work with such nested state, the `useIbiza` hook supports slicing.\n\nThe following example assumes you have an existing state object:\n\n```javascript\n{\n  user: {\n    name: 'Joel',\n    partner: {\n      name: 'Sam',\n    }\n  }\n}\n```\n\nPass a string to `useIbiza` to fetch a specific slice of state. The string should be the path to the\nobject that you want.\n\n```jsx\nconst App = () => {\n  const partner = useIbiza('user.partner')\n\n  return (\n    <div>\n      <h1>Hello {partner.name}</h1>\n      <button onClick={() => void (partner.name = 'Bob')}></button>\n    </div>\n  )\n}\n```\n\nNote that slicing is really only supported as a convenience, and will not generally help with\nperformance.\n\n## `createModel()`\n\nIbiza is at its most powerful when working with models. They provide reusability and flexibility.\n\nCreate a model using the `createModel` helper, where the first argument is the model name, and the\nsecond argument is the initial model state as a plain object.\n\n```javascript\n// model.js\n\nexport default createModel('user', {\n  firstName: 'Joel',\n  lastName: 'Moss',\n  children: [{ firstName: 'Ash' }, { firstName: 'Elijah' }, { firstName: 'Eve' }]\n})\n```\n\n`createModel` returns a hook which you can use. You can now import your model anywhere:\n\n```jsx\n// app.jsx\n\nimport useModel from './model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <div>\n      <h1>Hello {user.firstName}</h1>\n      <ul>\n        {user.children.map((child, i) => (\n          <li key={i}>{child.firstName}</li>\n        ))}\n      </ul>\n    </div>\n  )\n}\n```\n\n### Initial State\n\nSometimes you want to be able to define your model with some initial state that could be provided\ndynamically. For example, from component props or some other parameters.\n\n`createModel` can accept a function as its second argument. This function will be called on\ninitialisation with two arguments; the current `state` and any `props` passed to it when its hook is\nfirst called.\n\n```javascript\n// model.js\n\nexport default createModel('user', (state, props) => ({\n  firstName: 'Joel',\n  lastName: 'Moss'\n  ...props\n}))\n```\n\n```jsx\n// app.jsx\n\nimport useModel from './model'\n\nconst App = ({ yearOfBirth }) => {\n  const user = useModel({ yearOfBirth })\n\n  return (\n    <div>\n      <h1>\n        Hello {user.firstName}, you were born in {user.yearOfBirth}.\n      </h1>\n    </div>\n  )\n}\n```\n\n### Functions\n\nYou can use regular function in your model. They accept the current state as the first argument, and\n`this` will also be the current state (as long as you don't use hash rocket functions).\n\n```jsx\nconst App = () => {\n  const state = useIbiza({\n    count: 0,\n    increment: state => {\n      ++state.count\n    },\n    decrement() {\n      ++this.count\n    }\n  })\n\n  return (\n    <>\n      <h1>Count = {state.count}</h1>\n      <button onClick={state.increment}>Increment</button>\n      <button onClick={state.decrement}>Decrement</button>\n    </>\n  )\n}\n```\n\nWhen reading/writing state within a function, `this` responds to the state at the level where the\nfunction sits. This means that if the function is deeply nested, `this` will not include state lower\ndown.\n\nTo solve this, you can call `this.$model` to access your model, or `this.$root` to access the root\nof the store state.\n\n```javascript\nuseIbiza({\n  deepstate: {\n    user: {\n      name: 'Joel',\n      partner: {\n        name: 'Sam',\n\n        get partner() {\n          // `this` refers to 'deepstate.user.partner'.\n          // `this.$model` refers to 'deepstate.user'.\n          // `this.$root` is the whole store state.\n          return this.$model.name\n        }\n      }\n    }\n  }\n})\n```\n\nFunctions accept any number of arguments just like regular functions do, but don't forget that the\nfirst argument is always the state.\n\n```jsx\nconst App = () => {\n  const user = useIbiza({\n    children: [],\n    addChild(state, firstName, lastName) {\n      state.children.push({ firstName, lastName }) // or `this.children.push(...)`\n    }\n  })\n\n  return (\n    <>\n      <ul>\n        {user.children.map((child, i) => (\n          <li key={i}>\n            {child.firstName} {child.lastName}\n          </li>\n        ))}\n      </ul>\n      <button onClick={() => user.addChild('Ash', 'Moss')}></button>\n    </>\n  )\n}\n```\n\n### Getters and Setters\n\nIbiza supports Javascript getters and setters in your state and models.\n\n```javascript\nexport default createModel('user', {\n  firstName: 'Joel',\n  lastName: 'Moss',\n\n  get fullName() {\n    // You can read/write to your state via `this`.\n    return `${this.firstName} ${this.lastName}`\n  },\n\n  set fullName(value) {\n    const [firstName, lastName] = value.split(' ')\n\n    this.firstName = firstName\n    this.lastName = lastName\n  }\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <h1>Hello {user.fullName}</h1>\n      <button onClick={() => void (user.fullName = 'Bob Bones')}></button>\n    </>\n  )\n}\n```\n\n### Async Functions\n\nFunctions can be async and/or return Promises, and support React's Suspense by default.\n\n```javascript\nexport default createModel('user', {\n  name: 'Joel',\n\n  async doSomething() {\n    return await someAsyncAction()\n  }\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <h1>Hello {user.fullName}</h1>\n      <button onClick={user.doSomething}></button>\n    </>\n  )\n}\n```\n\n### URL Models\n\nBecause reading and writing to/from the server is so common, Ibiza has support to make this easy\nwith URL Models, similar to react-query. Simply use a valid and relative URL as your model name or\nslice.\n\nThe following will fetch the user from the server at `/user`, suspending the component while it does\nso. The data is fetched only when it does not exist in the store.\n\n```jsx\nconst App = () => {\n  const user = useIbiza('/user')\n\n  return <h1>Hello {user.name}</h1>\n}\n```\n\nYou can safely mutate your model, as all mutations will remain local.\n\nYou can write your model state back to the server. It the server responds with JSON, the model will\nbe updated with that response.\n\n```jsx\nconst App = () => {\n  const user = useIbiza('/user')\n\n  const renameUser = async () => {\n    await user.save({ body: { name: 'Bob' } })\n  }\n\n  return (\n    <>\n      <h1>Hello {user.name}</h1>\n      <button onClick={renameUser}></button>\n    </>\n  )\n}\n```\n\nURL Models can also be defined with `createModel`, and accept the same arguments:\n\n```javascript\nexport default createModel('/user')\n```\n\n`createModel` returns a hook which you can use. You can now import your model anywhere:\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return <h1>Hello {user.firstName}</h1>\n}\n```\n\nAdditionally, URL models accept a `fetcher` option, which when provided, will be used as the fetch\nfunction for the model:\n\n```javascript\nexport default createModel('/user', {}, { fetcher: myFetchFunction })\n```\n\n## `createContextModel()`\n\nWrap your component in the `IbizaProvider` higher order component, and instead of `createModel()`,\ncreate your model with `createContextModel()` function. The model will automatically be given a\nunique name specific to the wrapped components in IbizaProvider. Just pass the model definition as\nthe first argument. It accepts the same options as `createModel()` for the second argument.\n\n```jsx\nconst useModel = createContextModel(() => ({\n  // Your model definition...\n  name: 'Awesome!'\n}))\n\nconst App = () => {\n  return (\n    <IbizaProvider>\n      <MyComponent />\n    </IbizaProvider>\n  );\n};\n\nconst MyComponent = () => {\n  const model = useModel()\n\n  return <h1>My model is {model.name}</h1>\n};\n```\n\nEach instance of IbizaProvider will use its own state.\n\n```jsx\nconst useFirstModel = createContextModel(() => ({\n  name: 'FIRST!'\n}))\n\nconst useSecondModel = createContextModel(() => ({\n  name: 'SECOND!'\n}))\n\nconst App = () => {\n  return (\n    <>\n      <IbizaProvider>\n        <MyFirstComponent />\n      </IbizaProvider>\n      <IbizaProvider>\n        <MySecondComponent />\n      </IbizaProvider>\n    </>\n  );\n};\n\nconst MyFirstComponent = () => {\n  const model = useFirstModel();\n\n  return <h1>My model is {model.name}</h1>; // My model is FIRST!\n};\n\nconst MySecondComponent = () => {\n  const model = useSecondModel()\n\n  return <h1>My model is {model.name}</h1> // My model is SECOND!\n};\n```\n\n","_id":"ibiza@1.5.1","dist":{"shasum":"261126021feafecae3849e13f6a0b68d796b16db","integrity":"sha512-OQw4GUe524OameuIU1Dk7cz+FkFLOsT2pKuT+4ZPl5MoCFfFGWRqv+ugoYKUatuFkNaiXyK54yuQmW/OUh50Aw==","tarball":"https://registry.npmjs.org/ibiza/-/ibiza-1.5.1.tgz","fileCount":12,"unpackedSize":302094,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDRNaWc6GEtAT24RHNiTyy8kGL5UDbWczh2GcbgpYlnSQIhAMB45oK0VT5cd9tSTgz7IoDYlH0OZV+aVoobzapzTU8r"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiqbjuACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmp9BQ//Xsb5qRtRPk3InUJDxdovDjUP5AAWvMDiPLln4c1SNVx8UzON\r\nXuSkqlLOQ6yFNOHWS8zkDT9zEyiGYUC54eQlBLIG8/uc+80BGkPx0DzSSAkT\r\nWEcQ5GL/3f/ZHu/GeowvCzK3Mz++9a7HtH4tmwkGuj/7zHKnmmPQCaaz9yjx\r\nWCK7hAGCsCcmwOkqCkY9P4fpMCTDsxFaJgZwK/Zmr9BMecNR17C0T0AFUnbU\r\nujBLlC/xesxcSCtnDx7WifHBV+A+6EIzQKoGv14lLII89gJqKos34+Hg1N0i\r\nzQiWiLbCo4TeQinGv4cjiHqhCUpkzi5/mirJlMM1gSuPqLRvhqBtua5LDmM1\r\nWJwrgo7G+51SaWsv0GyG05EayBNSU5miVjqEbd2SWOKyZ4OOpopPmbtcDNEU\r\n4FxjhePxvls+VlRZT/YHdbiTXZS4/QRuasliJgIGqW8qHJmmilavQQxR4YUK\r\nh2enOB1RTSoUwNXLHpgZrmkdhgednkrFDeeaPT+XXN4whQ5MvhtgUJVBcUAN\r\nJSm1a/SgJFQismSad7eXlE0Ol0siIqfiAOrrePJocv5PgcSZsnoprtsNuiJY\r\nDspfU4M0mwHg+xrt8yQhWcHw+ijGCTH2CvGGFFiIanKpECHIqIycYKcRr07S\r\nfEiL7haT2GbYYp7ERGpcEmCDoB82fPvzX6k=\r\n=yTRH\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"joelmoss","email":"joel@developwithstyle.com"},"directories":{},"maintainers":[{"name":"joelmoss","email":"joel@developwithstyle.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ibiza_1.5.1_1655290093964_0.07118345100059265"},"_hasShrinkwrap":false},"2.0.0-alpha.1":{"name":"ibiza","author":{"name":"Joel Moss"},"version":"2.0.0-alpha.1","description":"React State Management for Party Animals","license":"MIT","homepage":"https://github.com/joelmoss/ibiza","repository":{"type":"git","url":"git+https://github.com/joelmoss/ibiza.git"},"bugs":{"url":"https://github.com/joelmoss/ibiza/issues"},"keywords":["react","state","proxy"],"type":"module","source":"src/index.js","main":"dist/ibiza.cjs","module":"dist/ibiza.module.js","unpkg":"dist/ibiza.umd.js","exports":{"require":"./dist/ibiza.cjs","default":"./dist/ibiza.modern.js"},"sideEffects":false,"eslintConfig":{"extends":["eslint:recommended","plugin:react/recommended","plugin:react-hooks/recommended","plugin:prettier/recommended"],"settings":{"react":{"version":"detect"}},"env":{"browser":true,"node":false,"es6":true},"parserOptions":{"ecmaVersion":"latest","sourceType":"module","ecmaFeatures":{"jsx":true}},"rules":{"react/prop-types":0},"overrides":[{"files":["test/**"],"extends":["plugin:jest/recommended","plugin:testing-library/react","plugin:jest/style"],"rules":{"jest/expect-expect":["warn",{"assertFunctionNames":["expect","screen.findByText","screen.getByText"]}]}}]},"size-limit":[{"name":"useIbiza","path":"./src/index.js","import":"{ useIbiza }","limit":"1 s"},{"name":"store","path":"./src/index.js","import":"{ store }","limit":"1 s"},{"name":"createModel","path":"./src/index.js","import":"{ createModel }","limit":"1 s"},{"name":"rawStateOf","path":"./src/index.js","import":"{ rawStateOf }","limit":"1 s"},{"name":"freeze","path":"./src/index.js","import":"{ freeze }","limit":"1 s"}],"prettier":{"trailingComma":"none","printWidth":100,"semi":false,"singleQuote":true,"arrowParens":"avoid"},"peerDependencies":{"react":">=17"},"devDependencies":{"@size-limit/preset-big-lib":"^7.0.1","@swc/core":"^1.2.144","@swc/jest":"^0.2.17","@testing-library/jest-dom":"^5.15.0","@testing-library/react":"^13.0.0","cross-fetch":"^3.1.4","eslint":"^8.18.0","eslint-config-prettier":"^8.5.0","eslint-plugin-jest":"^26.5.3","eslint-plugin-prettier":"^4.0.0","eslint-plugin-react":"^7.30.0","eslint-plugin-react-hooks":"^4.6.0","eslint-plugin-testing-library":"^5.5.1","fetch-mock-jest":"^1.5.1","ibiza":"link:./ibiza","jest":"^28.1.0","jest-environment-jsdom":"^28.1.0","microbundle":"^0.15.0","msw":"^0.42","prettier":"^2.7.1","react":"^18.2.0","react-dom":"^18.2.0","react-error-boundary":"^3.1.4","rimraf":"^3.0.2","size-limit":"^7.0.0"},"dependencies":{"fast-equals":"^4.0.0","micro-memoize":"^4.0.9","use-sync-external-store":"^1.2.0"},"scripts":{"clean":"rimraf dist","test":"jest","build":"microbundle --jsx React.createElement","dev":"microbundle watch --jsx React.createElement","size":"microbundle && size-limit","lint":"eslint src test --ext .jsx --ext .js"},"readme":"# Ibiza - React State Management for Party Animals\n\nIbiza gets out of your way and simply lets you read and write state as you would with regular\nJavascript assignment. It maintains a global state object and is smart enough to know when to\nrerender your components based on state usage and modification.\n\n## `useIbiza()` ✨\n\nA component calls the `useIbiza` React hook, which returns the store state as a JS Proxy object.\nThis Proxy records when a state property is accessed or \"used\". Then when that property is mutated,\nthe component is rerendered.\n\nThis means that you can mutate your state in any way, but your component will only rerender if you\nmutate state that you have used.\n\nThe following component will rerender when the button is clicked, because `name` has changed.\n\n```jsx\nimport { useIbiza } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n      <button onClick={() => void (state.name = 'Joel')}></button>\n    </div>\n  )\n}\n```\n\nThe following component will not rerender when the button is clicked, because even though `age` has\nbeen mutated, it is not actually being used within the component.\n\n```jsx\nimport { useIbiza } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n      <button onClick={() => void (state.age = 44)}></button>\n    </div>\n  )\n}\n```\n\nState can be mutated from anywhere - not just from within a component:\n\n```js\nimport { useIbiza, store } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n    </div>\n  )\n}\n\n// <App> component will re-render when this line executes, as `name` has changed.\nstore.state.name = 'Ash'\n```\n\n### Initial State\n\nYou can pass some initial state to `useIbiza` which will be merged with existing state in the Ibiza\nstore.\n\n```jsx\nconst App = () => {\n  const state = useIbiza({ user: { name: 'Joel' } })\n\n  return <h1>Hello {state.user.name}</h1>\n}\n```\n\nThis is safe to include in the body of your component, as it will only be merged into the store on\nfirst render.\n\n### Slicing\n\nIbiza supports deeply nested objects, allowing you to design the shape of your state any way you\nlike. To help you work with such nested state, the `useIbiza` hook supports slicing.\n\nThe following example assumes you have an existing state object:\n\n```javascript\n{\n  user: {\n    name: 'Joel',\n    partner: {\n      name: 'Sam',\n    }\n  }\n}\n```\n\nPass a string to `useIbiza` to fetch a specific slice of state. The string should be the path to the\nobject that you want.\n\n```jsx\nconst App = () => {\n  const partner = useIbiza('user.partner')\n\n  return (\n    <div>\n      <h1>Hello {partner.name}</h1>\n      <button onClick={() => void (partner.name = 'Bob')}></button>\n    </div>\n  )\n}\n```\n\nNote that slicing is really only supported as a convenience, and will not generally help with\nperformance.\n\n## `createModel()`\n\nIbiza is at its most powerful when working with models. They provide reusability and flexibility.\n\nCreate a model using the `createModel` helper, where the first argument is the model name, and the\nsecond argument is the initial model state as a plain object.\n\n```javascript\n// model.js\n\nexport default createModel('user', {\n  firstName: 'Joel',\n  lastName: 'Moss',\n  children: [{ firstName: 'Ash' }, { firstName: 'Elijah' }, { firstName: 'Eve' }]\n})\n```\n\n`createModel` returns a hook which you can use. You can now import your model anywhere:\n\n```jsx\n// app.jsx\n\nimport useModel from './model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <div>\n      <h1>Hello {user.firstName}</h1>\n      <ul>\n        {user.children.map((child, i) => (\n          <li key={i}>{child.firstName}</li>\n        ))}\n      </ul>\n    </div>\n  )\n}\n```\n\n### Initial State\n\nSometimes you want to be able to define your model with some initial state that could be provided\ndynamically. For example, from component props or some other parameters.\n\n`createModel` can accept a function as its second argument. This function will be called on\ninitialisation with two arguments; the current `state` and any `props` passed to it when its hook is\nfirst called.\n\n```javascript\n// model.js\n\nexport default createModel('user', (state, props) => ({\n  firstName: 'Joel',\n  lastName: 'Moss'\n  ...props\n}))\n```\n\n```jsx\n// app.jsx\n\nimport useModel from './model'\n\nconst App = ({ yearOfBirth }) => {\n  const user = useModel({ yearOfBirth })\n\n  return (\n    <div>\n      <h1>\n        Hello {user.firstName}, you were born in {user.yearOfBirth}.\n      </h1>\n    </div>\n  )\n}\n```\n\n### Functions\n\nYou can use regular function in your model. They accept the current state as the first argument, and\n`this` will also be the current state (as long as you don't use hash rocket functions).\n\n```jsx\nconst App = () => {\n  const state = useIbiza({\n    count: 0,\n    increment: state => {\n      ++state.count\n    },\n    decrement() {\n      ++this.count\n    }\n  })\n\n  return (\n    <>\n      <h1>Count = {state.count}</h1>\n      <button onClick={state.increment}>Increment</button>\n      <button onClick={state.decrement}>Decrement</button>\n    </>\n  )\n}\n```\n\nWhen reading/writing state within a function, `this` responds to the state at the level where the\nfunction sits. This means that if the function is deeply nested, `this` will not include state lower\ndown.\n\nTo solve this, you can call `this.$model` to access your model, or `this.$root` to access the root\nof the store state.\n\n```javascript\nuseIbiza({\n  deepstate: {\n    user: {\n      name: 'Joel',\n      partner: {\n        name: 'Sam',\n\n        get partner() {\n          // `this` refers to 'deepstate.user.partner'.\n          // `this.$model` refers to 'deepstate.user'.\n          // `this.$root` is the whole store state.\n          return this.$model.name\n        }\n      }\n    }\n  }\n})\n```\n\nFunctions accept any number of arguments just like regular functions do, but don't forget that the\nfirst argument is always the state.\n\n```jsx\nconst App = () => {\n  const user = useIbiza({\n    children: [],\n    addChild(state, firstName, lastName) {\n      state.children.push({ firstName, lastName }) // or `this.children.push(...)`\n    }\n  })\n\n  return (\n    <>\n      <ul>\n        {user.children.map((child, i) => (\n          <li key={i}>\n            {child.firstName} {child.lastName}\n          </li>\n        ))}\n      </ul>\n      <button onClick={() => user.addChild('Ash', 'Moss')}></button>\n    </>\n  )\n}\n```\n\n### Getters and Setters\n\nIbiza supports Javascript getters and setters in your state and models.\n\n```javascript\nexport default createModel('user', {\n  firstName: 'Joel',\n  lastName: 'Moss',\n\n  get fullName() {\n    // You can read/write to your state via `this`.\n    return `${this.firstName} ${this.lastName}`\n  },\n\n  set fullName(value) {\n    const [firstName, lastName] = value.split(' ')\n\n    this.firstName = firstName\n    this.lastName = lastName\n  }\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <h1>Hello {user.fullName}</h1>\n      <button onClick={() => void (user.fullName = 'Bob Bones')}></button>\n    </>\n  )\n}\n```\n\n### Async Functions\n\nFunctions can be async and/or return Promises, and support React's Suspense by default.\n\n```javascript\nexport default createModel('user', {\n  name: 'Joel',\n\n  async doSomething() {\n    return await someAsyncAction()\n  }\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <h1>Hello {user.fullName}</h1>\n      <button onClick={user.doSomething}></button>\n    </>\n  )\n}\n```\n\n### URL Models\n\nBecause reading and writing to/from the server is so common, Ibiza has support to make this easy\nwith URL Models, similar to react-query. Simply use a valid and relative URL as your model name or\nslice.\n\nThe following will fetch the user from the server at `/user`, suspending the component while it does\nso. The data is fetched only when it does not exist in the store.\n\n```jsx\nconst App = () => {\n  const user = useIbiza('/user')\n\n  return <h1>Hello {user.name}</h1>\n}\n```\n\nYou can safely mutate your model, as all mutations will remain local.\n\nYou can write your model state back to the server. It the server responds with JSON, the model will\nbe updated with that response.\n\n```jsx\nconst App = () => {\n  const user = useIbiza('/user')\n\n  const renameUser = async () => {\n    await user.save({ body: { name: 'Bob' } })\n  }\n\n  return (\n    <>\n      <h1>Hello {user.name}</h1>\n      <button onClick={renameUser}></button>\n    </>\n  )\n}\n```\n\nURL Models can also be defined with `createModel`, and accept the same arguments:\n\n```javascript\nexport default createModel('/user')\n```\n\n`createModel` returns a hook which you can use. You can now import your model anywhere:\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return <h1>Hello {user.firstName}</h1>\n}\n```\n\nAdditionally, URL models accept a `fetcher` option, which when provided, will be used as the fetch\nfunction for the model:\n\n```javascript\nexport default createModel('/user', {}, { fetcher: myFetchFunction })\n```\n\n## `createContextModel()`\n\nWrap your component in the `IbizaProvider` higher order component, and instead of `createModel()`,\ncreate your model with `createContextModel()` function. The model will automatically be given a\nunique name specific to the wrapped components in IbizaProvider. Just pass the model definition as\nthe first argument. It accepts the same options as `createModel()` for the second argument.\n\n```jsx\nconst useModel = createContextModel(() => ({\n  // Your model definition...\n  name: 'Awesome!'\n}))\n\nconst App = () => {\n  return (\n    <IbizaProvider>\n      <MyComponent />\n    </IbizaProvider>\n  );\n};\n\nconst MyComponent = () => {\n  const model = useModel()\n\n  return <h1>My model is {model.name}</h1>\n};\n```\n\nEach instance of IbizaProvider will use its own state.\n\n```jsx\nconst useFirstModel = createContextModel(() => ({\n  name: 'FIRST!'\n}))\n\nconst useSecondModel = createContextModel(() => ({\n  name: 'SECOND!'\n}))\n\nconst App = () => {\n  return (\n    <>\n      <IbizaProvider>\n        <MyFirstComponent />\n      </IbizaProvider>\n      <IbizaProvider>\n        <MySecondComponent />\n      </IbizaProvider>\n    </>\n  );\n};\n\nconst MyFirstComponent = () => {\n  const model = useFirstModel();\n\n  return <h1>My model is {model.name}</h1>; // My model is FIRST!\n};\n\nconst MySecondComponent = () => {\n  const model = useSecondModel()\n\n  return <h1>My model is {model.name}</h1> // My model is SECOND!\n};\n```\n\n","readmeFilename":"README.md","_id":"ibiza@2.0.0-alpha.1","_integrity":"sha512-WMdOdr9lydqBfL8mi2kyjvj2Qmo7QOnIEjamlIA0X8MhfGwrcdW0YvlWewiEcPs8Q5F7fkaAiHr/CicUYApeEA==","_resolved":"/private/var/folders/3b/b6pthvr51cg1755k2jxx8www0000gn/T/cda6ee3b5dd7afde2708d3d45fc8360a/ibiza-2.0.0-alpha.1.tgz","_from":"file:ibiza-2.0.0-alpha.1.tgz","_nodeVersion":"18.4.0","_npmVersion":"8.12.1","dist":{"integrity":"sha512-WMdOdr9lydqBfL8mi2kyjvj2Qmo7QOnIEjamlIA0X8MhfGwrcdW0YvlWewiEcPs8Q5F7fkaAiHr/CicUYApeEA==","shasum":"fc69b13c46690a22e31c5527fa8caed679eba2be","tarball":"https://registry.npmjs.org/ibiza/-/ibiza-2.0.0-alpha.1.tgz","fileCount":10,"unpackedSize":317908,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD/xRf9Wt2nzPkqN0h1yBVBu0M3r39QBZiDRY1i7gzcwAIhAJXSJaN5OIeAKWMRVEivcSMZos/qyhpYosu+t1DbWfx7"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiszJ0ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmq3dQ/+OBHusqkukMxfjHn4ln3ysXKnKoKTbxzWUN76/xLc/eyDAEAD\r\n/bClHvLT83WvWrHMzRxvIJYNgIz1BRD97wnO6L50AXdGtJSSFAatCZeS7nXi\r\nACo4YflzSMG0ZQ3y1/TAEsPR24FQQSbPkDI9SW6hIFqDMoYgYe6UBF/dysuN\r\n8J+O5yHToY3129iQPuQDzQROs1kKnjZwmaflSYbJMc+SLss+O9ixjdfqMtO2\r\niotCK/NZThzvb7nAjnAy30Ewpsg7Cfbki+BNaxDk1aasgs0cDi45HaBs/Z5N\r\n/wojdI/AOBKiQ1l3KTYnPlxfdOV+qI1R0Rogvvp8UVGar3F9OYyQNd7qAiMf\r\nevKbbFTJPDPdUpvLt+h2sGKaH9Q5EOo0SfwLAvaA1eIci+3TuuKekCQx7hcE\r\n9DKk9/CGk5IdOHcv+JJ/hKo8bksLkSHdQFPcxPnrimcysHtBZdIbWbc9cUK9\r\nkEnwVj4G5nQnBks0/T5hJsGpNPzg6vvsjZhfmPATXy0ZVQk6w8kPKSUYSQAa\r\nO+mHkf1B/CVLR7VQVMxs8jub8WrwPULyj6BqrsDuctbR5o6tXN4KFYydvhw2\r\nM22l2dhlUq2eCoXB7UR+K58iC+0XExuh/5lkeJAOUVxjUfBXCCYQwrLLweYu\r\nlZJE03IlQcD8KUeyT32jOwPhghiC3CogNKI=\r\n=+hqx\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"joelmoss","email":"joel@developwithstyle.com"},"directories":{},"maintainers":[{"name":"joelmoss","email":"joel@developwithstyle.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ibiza_2.0.0-alpha.1_1655911028440_0.7706774293793399"},"_hasShrinkwrap":false},"2.0.0-alpha.2":{"name":"ibiza","author":{"name":"Joel Moss"},"version":"2.0.0-alpha.2","description":"React State Management for Party Animals","license":"MIT","homepage":"https://github.com/joelmoss/ibiza","repository":{"type":"git","url":"git+https://github.com/joelmoss/ibiza.git"},"bugs":{"url":"https://github.com/joelmoss/ibiza/issues"},"keywords":["react","state","proxy"],"type":"module","source":"src/index.js","main":"dist/ibiza.cjs","module":"dist/ibiza.module.js","unpkg":"dist/ibiza.umd.js","exports":{"require":"./dist/ibiza.cjs","default":"./dist/ibiza.modern.js"},"sideEffects":false,"eslintConfig":{"extends":["eslint:recommended","plugin:react/recommended","plugin:react-hooks/recommended","plugin:prettier/recommended"],"settings":{"react":{"version":"detect"}},"env":{"browser":true,"node":false,"es6":true},"parserOptions":{"ecmaVersion":"latest","sourceType":"module","ecmaFeatures":{"jsx":true}},"rules":{"react/prop-types":0},"overrides":[{"files":["test/**"],"extends":["plugin:jest/recommended","plugin:testing-library/react","plugin:jest/style"],"rules":{"jest/expect-expect":["warn",{"assertFunctionNames":["expect","screen.findByText","screen.getByText"]}]}}]},"size-limit":[{"name":"useIbiza","path":"./src/index.js","import":"{ useIbiza }","limit":"1 s"},{"name":"store","path":"./src/index.js","import":"{ store }","limit":"1 s"},{"name":"createModel","path":"./src/index.js","import":"{ createModel }","limit":"1 s"},{"name":"rawStateOf","path":"./src/index.js","import":"{ rawStateOf }","limit":"1 s"},{"name":"freeze","path":"./src/index.js","import":"{ freeze }","limit":"1 s"}],"prettier":{"trailingComma":"none","printWidth":100,"semi":false,"singleQuote":true,"arrowParens":"avoid"},"peerDependencies":{"react":">=17"},"devDependencies":{"@size-limit/preset-big-lib":"^7.0.1","@swc/core":"^1.2.144","@swc/jest":"^0.2.17","@testing-library/jest-dom":"^5.15.0","@testing-library/react":"^13.0.0","cross-fetch":"^3.1.4","eslint":"^8.18.0","eslint-config-prettier":"^8.5.0","eslint-plugin-jest":"^26.5.3","eslint-plugin-prettier":"^4.0.0","eslint-plugin-react":"^7.30.0","eslint-plugin-react-hooks":"^4.6.0","eslint-plugin-testing-library":"^5.5.1","fetch-mock-jest":"^1.5.1","ibiza":"link:./ibiza","jest":"^28.1.0","jest-environment-jsdom":"^28.1.0","microbundle":"^0.15.0","msw":"^0.42","prettier":"^2.7.1","react":"^18.2.0","react-dom":"^18.2.0","react-error-boundary":"^3.1.4","rimraf":"^3.0.2","size-limit":"^7.0.0"},"dependencies":{"fast-equals":"^4.0.0","micro-memoize":"^4.0.9","use-sync-external-store":"^1.2.0"},"scripts":{"clean":"rimraf dist","test":"jest","build":"microbundle --jsx React.createElement","dev":"microbundle watch --jsx React.createElement --compress false","size":"microbundle && size-limit","lint":"eslint src test --ext .jsx --ext .js"},"readme":"# Ibiza - React State Management for Party Animals\n\nIbiza gets out of your way and simply lets you read and write state as you would with regular\nJavascript assignment. It maintains a global state object and is smart enough to know when to\nrerender your components based on state usage and modification.\n\n## `useIbiza()` ✨\n\nA component calls the `useIbiza` React hook, which returns the store state as a JS Proxy object.\nThis Proxy records when a state property is accessed or \"used\". Then when that property is mutated,\nthe component is rerendered.\n\nThis means that you can mutate your state in any way, but your component will only rerender if you\nmutate state that you have used.\n\nThe following component will rerender when the button is clicked, because `name` has changed.\n\n```jsx\nimport { useIbiza } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n      <button onClick={() => void (state.name = 'Joel')}></button>\n    </div>\n  )\n}\n```\n\nThe following component will not rerender when the button is clicked, because even though `age` has\nbeen mutated, it is not actually being used within the component.\n\n```jsx\nimport { useIbiza } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n      <button onClick={() => void (state.age = 44)}></button>\n    </div>\n  )\n}\n```\n\nState can be mutated from anywhere - not just from within a component:\n\n```js\nimport { useIbiza, store } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n    </div>\n  )\n}\n\n// <App> component will re-render when this line executes, as `name` has changed.\nstore.state.name = 'Ash'\n```\n\n### Initial State\n\nYou can pass some initial state to `useIbiza` which will be merged with existing state in the Ibiza\nstore.\n\n```jsx\nconst App = () => {\n  const state = useIbiza({ user: { name: 'Joel' } })\n\n  return <h1>Hello {state.user.name}</h1>\n}\n```\n\nThis is safe to include in the body of your component, as it will only be merged into the store on\nfirst render.\n\n### Slicing\n\nIbiza supports deeply nested objects, allowing you to design the shape of your state any way you\nlike. To help you work with such nested state, the `useIbiza` hook supports slicing.\n\nThe following example assumes you have an existing state object:\n\n```javascript\n{\n  user: {\n    name: 'Joel',\n    partner: {\n      name: 'Sam',\n    }\n  }\n}\n```\n\nPass a string to `useIbiza` to fetch a specific slice of state. The string should be the path to the\nobject that you want.\n\n```jsx\nconst App = () => {\n  const partner = useIbiza('user.partner')\n\n  return (\n    <div>\n      <h1>Hello {partner.name}</h1>\n      <button onClick={() => void (partner.name = 'Bob')}></button>\n    </div>\n  )\n}\n```\n\nNote that slicing is really only supported as a convenience, and will not generally help with\nperformance.\n\n## `createModel()`\n\nIbiza is at its most powerful when working with models. They provide reusability and flexibility.\n\nCreate a model using the `createModel` helper, where the first argument is the model name, and the\nsecond argument is the initial model state as a plain object.\n\n```javascript\n// model.js\n\nexport default createModel('user', {\n  firstName: 'Joel',\n  lastName: 'Moss',\n  children: [{ firstName: 'Ash' }, { firstName: 'Elijah' }, { firstName: 'Eve' }]\n})\n```\n\n`createModel` returns a hook which you can use. You can now import your model anywhere:\n\n```jsx\n// app.jsx\n\nimport useModel from './model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <div>\n      <h1>Hello {user.firstName}</h1>\n      <ul>\n        {user.children.map((child, i) => (\n          <li key={i}>{child.firstName}</li>\n        ))}\n      </ul>\n    </div>\n  )\n}\n```\n\n### Initial State\n\nSometimes you want to be able to define your model with some initial state that could be provided\ndynamically. For example, from component props or some other parameters.\n\n`createModel` can accept a function as its second argument. This function will be called on\ninitialisation with two arguments; the current `state` and any `props` passed to it when its hook is\nfirst called.\n\n```javascript\n// model.js\n\nexport default createModel('user', (state, props) => ({\n  firstName: 'Joel',\n  lastName: 'Moss'\n  ...props\n}))\n```\n\n```jsx\n// app.jsx\n\nimport useModel from './model'\n\nconst App = ({ yearOfBirth }) => {\n  const user = useModel({ yearOfBirth })\n\n  return (\n    <div>\n      <h1>\n        Hello {user.firstName}, you were born in {user.yearOfBirth}.\n      </h1>\n    </div>\n  )\n}\n```\n\n### Functions\n\nYou can use regular function in your model. They accept the current state as the first argument, and\n`this` will also be the current state (as long as you don't use hash rocket functions).\n\n```jsx\nconst App = () => {\n  const state = useIbiza({\n    count: 0,\n    increment: state => {\n      ++state.count\n    },\n    decrement() {\n      ++this.count\n    }\n  })\n\n  return (\n    <>\n      <h1>Count = {state.count}</h1>\n      <button onClick={state.increment}>Increment</button>\n      <button onClick={state.decrement}>Decrement</button>\n    </>\n  )\n}\n```\n\nWhen reading/writing state within a function, `this` responds to the state at the level where the\nfunction sits. This means that if the function is deeply nested, `this` will not include state lower\ndown.\n\nTo solve this, you can call `this.$model` to access your model, or `this.$root` to access the root\nof the store state.\n\n```javascript\nuseIbiza({\n  deepstate: {\n    user: {\n      name: 'Joel',\n      partner: {\n        name: 'Sam',\n\n        get partner() {\n          // `this` refers to 'deepstate.user.partner'.\n          // `this.$model` refers to 'deepstate.user'.\n          // `this.$root` is the whole store state.\n          return this.$model.name\n        }\n      }\n    }\n  }\n})\n```\n\nFunctions accept any number of arguments just like regular functions do, but don't forget that the\nfirst argument is always the state.\n\n```jsx\nconst App = () => {\n  const user = useIbiza({\n    children: [],\n    addChild(state, firstName, lastName) {\n      state.children.push({ firstName, lastName }) // or `this.children.push(...)`\n    }\n  })\n\n  return (\n    <>\n      <ul>\n        {user.children.map((child, i) => (\n          <li key={i}>\n            {child.firstName} {child.lastName}\n          </li>\n        ))}\n      </ul>\n      <button onClick={() => user.addChild('Ash', 'Moss')}></button>\n    </>\n  )\n}\n```\n\n### Getters and Setters\n\nIbiza supports Javascript getters and setters in your state and models.\n\n```javascript\nexport default createModel('user', {\n  firstName: 'Joel',\n  lastName: 'Moss',\n\n  get fullName() {\n    // You can read/write to your state via `this`.\n    return `${this.firstName} ${this.lastName}`\n  },\n\n  set fullName(value) {\n    const [firstName, lastName] = value.split(' ')\n\n    this.firstName = firstName\n    this.lastName = lastName\n  }\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <h1>Hello {user.fullName}</h1>\n      <button onClick={() => void (user.fullName = 'Bob Bones')}></button>\n    </>\n  )\n}\n```\n\n### Async Functions\n\nFunctions can be async and/or return Promises, and support React's Suspense by default.\n\n```javascript\nexport default createModel('user', {\n  name: 'Joel',\n\n  async doSomething() {\n    return await someAsyncAction()\n  }\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <h1>Hello {user.fullName}</h1>\n      <button onClick={user.doSomething}></button>\n    </>\n  )\n}\n```\n\n### URL Models\n\nBecause reading and writing to/from the server is so common, Ibiza has support to make this easy\nwith URL Models, similar to react-query. Simply use a valid and relative URL as your model name or\nslice.\n\nThe following will fetch the user from the server at `/user`, suspending the component while it does\nso. The data is fetched only when it does not exist in the store.\n\n```jsx\nconst App = () => {\n  const user = useIbiza('/user')\n\n  return <h1>Hello {user.name}</h1>\n}\n```\n\nYou can safely mutate your model, as all mutations will remain local.\n\nYou can write your model state back to the server. It the server responds with JSON, the model will\nbe updated with that response.\n\n```jsx\nconst App = () => {\n  const user = useIbiza('/user')\n\n  const renameUser = async () => {\n    await user.save({ body: { name: 'Bob' } })\n  }\n\n  return (\n    <>\n      <h1>Hello {user.name}</h1>\n      <button onClick={renameUser}></button>\n    </>\n  )\n}\n```\n\nURL Models can also be defined with `createModel`, and accept the same arguments:\n\n```javascript\nexport default createModel('/user')\n```\n\n`createModel` returns a hook which you can use. You can now import your model anywhere:\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return <h1>Hello {user.firstName}</h1>\n}\n```\n\nAdditionally, URL models accept a `fetcher` option, which when provided, will be used as the fetch\nfunction for the model:\n\n```javascript\nexport default createModel('/user', {}, { fetcher: myFetchFunction })\n```\n\n## `createContextModel()`\n\nWrap your component in the `IbizaProvider` higher order component, and instead of `createModel()`,\ncreate your model with `createContextModel()` function. The model will automatically be given a\nunique name specific to the wrapped components in IbizaProvider. Just pass the model definition as\nthe first argument. It accepts the same options as `createModel()` for the second argument.\n\n```jsx\nconst useModel = createContextModel(() => ({\n  // Your model definition...\n  name: 'Awesome!'\n}))\n\nconst App = () => {\n  return (\n    <IbizaProvider>\n      <MyComponent />\n    </IbizaProvider>\n  );\n};\n\nconst MyComponent = () => {\n  const model = useModel()\n\n  return <h1>My model is {model.name}</h1>\n};\n```\n\nEach instance of IbizaProvider will use its own state.\n\n```jsx\nconst useFirstModel = createContextModel(() => ({\n  name: 'FIRST!'\n}))\n\nconst useSecondModel = createContextModel(() => ({\n  name: 'SECOND!'\n}))\n\nconst App = () => {\n  return (\n    <>\n      <IbizaProvider>\n        <MyFirstComponent />\n      </IbizaProvider>\n      <IbizaProvider>\n        <MySecondComponent />\n      </IbizaProvider>\n    </>\n  );\n};\n\nconst MyFirstComponent = () => {\n  const model = useFirstModel();\n\n  return <h1>My model is {model.name}</h1>; // My model is FIRST!\n};\n\nconst MySecondComponent = () => {\n  const model = useSecondModel()\n\n  return <h1>My model is {model.name}</h1> // My model is SECOND!\n};\n```\n\n","readmeFilename":"README.md","_id":"ibiza@2.0.0-alpha.2","_integrity":"sha512-Qc8IwcSgKoclBAuASl/ueb5yVKEUrYUC/jFX/Szbj27qcifWMeHv/HsrHxkfbAJ5RnvFzSwhrys9laIZq5kxQQ==","_resolved":"/private/var/folders/3b/b6pthvr51cg1755k2jxx8www0000gn/T/1b50aedf134b37590f5a64d8c735d572/ibiza-2.0.0-alpha.2.tgz","_from":"file:ibiza-2.0.0-alpha.2.tgz","_nodeVersion":"18.4.0","_npmVersion":"8.12.1","dist":{"integrity":"sha512-Qc8IwcSgKoclBAuASl/ueb5yVKEUrYUC/jFX/Szbj27qcifWMeHv/HsrHxkfbAJ5RnvFzSwhrys9laIZq5kxQQ==","shasum":"8d7a11f33a90da761bb251e8934643145fb4231b","tarball":"https://registry.npmjs.org/ibiza/-/ibiza-2.0.0-alpha.2.tgz","fileCount":10,"unpackedSize":317525,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC+j3k1UVtW0pVKkZ8w476eYwlwXDe4Y3N6+BxzCnLQpQIhAOwzuBdxt8bWw3cyBmFdFTAKUGN47RWUvnHunnPvxGPp"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJis1iLACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmo/Pg//QnGQg0ihpp9hxmWMqCGCL074NmKVvhBN8Fxyr2LrrmBDT4Ud\r\nAJF0TIhSBNYjr/mkRIih8+W4R87dpI2C29BYm54qkzeLfoDvePqotoj6LITg\r\nKA1s96acQc5pHTSocddqC5Q6DrkFiY46DejD9AUwi9+i5BcnpqYTd5t2EAJQ\r\nzqQYxKZ7eOVR8ePeebewj0+qwLnUc3KEoH3CsKAmTMn4ROdN4f0b9Z9AqQWS\r\nlw+5gMVcz63EFyLJESHxp+/2V+VQmSEDtZv8TTZnw7DShnX0N8CcvNrkVsDT\r\nO1YCZxi9OWYN9PTWz8tv78b9DZGv6V2HYYe825N7D3WtXdmm0pmSdKRVvWgp\r\nLtfoJ1kgQDeXE9l37pAF7wcDPQhr8gUcvDWHXwhwrxauodvSDKuuxn80r+/g\r\nd6ZiNlNKB5pnIOoaQKr6bhItSv5NQfWV5+B5XQzpJeIcyFFoj5b9W6g/NJpU\r\nUGZa3SwR4MZvC7mLiIm+RDv69jGwXg5AYCsYae1edgR8kB8csWD9IaSvtrig\r\nOyihqOmVZCdjYbglQ3V/9IEnRqkvsQvmR78p/thKCP1zyhQfqJEl+4pgv8D9\r\nPqtFxZdwM8Jsa2zpcbUQtJPIMP00n6M81DD+UP0iFIG7EjAK9h13Z8gzma57\r\ndx+MeL4n6l7CFZ5gYqdPhOTSaVD2wdEeg94=\r\n=txb3\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"joelmoss","email":"joel@developwithstyle.com"},"directories":{},"maintainers":[{"name":"joelmoss","email":"joel@developwithstyle.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ibiza_2.0.0-alpha.2_1655920779103_0.9939613328412364"},"_hasShrinkwrap":false},"2.0.0-alpha.3":{"name":"ibiza","author":{"name":"Joel Moss"},"version":"2.0.0-alpha.3","description":"React State Management for Party Animals","license":"MIT","homepage":"https://github.com/joelmoss/ibiza","repository":{"type":"git","url":"git+https://github.com/joelmoss/ibiza.git"},"bugs":{"url":"https://github.com/joelmoss/ibiza/issues"},"keywords":["react","state","proxy"],"type":"module","source":"src/index.js","main":"dist/ibiza.cjs","module":"dist/ibiza.module.js","unpkg":"dist/ibiza.umd.js","exports":{"require":"./dist/ibiza.cjs","default":"./dist/ibiza.modern.js"},"sideEffects":false,"eslintConfig":{"extends":["eslint:recommended","plugin:react/recommended","plugin:react-hooks/recommended","plugin:prettier/recommended"],"settings":{"react":{"version":"detect"}},"env":{"browser":true,"node":false,"es6":true},"parserOptions":{"ecmaVersion":"latest","sourceType":"module","ecmaFeatures":{"jsx":true}},"rules":{"react/prop-types":0},"overrides":[{"files":["test/**"],"extends":["plugin:jest/recommended","plugin:testing-library/react","plugin:jest/style"],"rules":{"jest/expect-expect":["warn",{"assertFunctionNames":["expect","screen.findByText","screen.getByText"]}]}}]},"size-limit":[{"name":"useIbiza","path":"./src/index.js","import":"{ useIbiza }","limit":"1 s"},{"name":"store","path":"./src/index.js","import":"{ store }","limit":"1 s"},{"name":"createModel","path":"./src/index.js","import":"{ createModel }","limit":"1 s"},{"name":"rawStateOf","path":"./src/index.js","import":"{ rawStateOf }","limit":"1 s"},{"name":"freeze","path":"./src/index.js","import":"{ freeze }","limit":"1 s"}],"prettier":{"trailingComma":"none","printWidth":100,"semi":false,"singleQuote":true,"arrowParens":"avoid"},"peerDependencies":{"react":">=17"},"devDependencies":{"@size-limit/preset-big-lib":"^7.0.1","@swc/core":"^1.2.144","@swc/jest":"^0.2.17","@testing-library/jest-dom":"^5.15.0","@testing-library/react":"^13.0.0","cross-fetch":"^3.1.4","eslint":"^8.18.0","eslint-config-prettier":"^8.5.0","eslint-plugin-jest":"^26.5.3","eslint-plugin-prettier":"^4.0.0","eslint-plugin-react":"^7.30.0","eslint-plugin-react-hooks":"^4.6.0","eslint-plugin-testing-library":"^5.5.1","fetch-mock-jest":"^1.5.1","ibiza":"link:./ibiza","jest":"^28.1.0","jest-environment-jsdom":"^28.1.0","microbundle":"^0.15.0","msw":"^0.42","prettier":"^2.7.1","react":"^18.2.0","react-dom":"^18.2.0","react-error-boundary":"^3.1.4","rimraf":"^3.0.2","size-limit":"^7.0.0"},"dependencies":{"fast-equals":"^4.0.0","micro-memoize":"^4.0.9","use-sync-external-store":"^1.2.0"},"scripts":{"clean":"rimraf dist","test":"jest","build":"microbundle --jsx React.createElement","dev":"microbundle watch --jsx React.createElement --compress false","size":"microbundle && size-limit","lint":"eslint src test --ext .jsx --ext .js"},"readme":"# Ibiza - React State Management for Party Animals\n\nIbiza gets out of your way and simply lets you read and write state as you would with regular\nJavascript assignment. It maintains a global state object and is smart enough to know when to\nrerender your components based on state usage and modification.\n\n## `useIbiza()` ✨\n\nA component calls the `useIbiza` React hook, which returns the store state as a JS Proxy object.\nThis Proxy records when a state property is accessed or \"used\". Then when that property is mutated,\nthe component is rerendered.\n\nThis means that you can mutate your state in any way, but your component will only rerender if you\nmutate state that you have used.\n\nThe following component will rerender when the button is clicked, because `name` has changed.\n\n```jsx\nimport { useIbiza } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n      <button onClick={() => void (state.name = 'Joel')}></button>\n    </div>\n  )\n}\n```\n\nThe following component will not rerender when the button is clicked, because even though `age` has\nbeen mutated, it is not actually being used within the component.\n\n```jsx\nimport { useIbiza } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n      <button onClick={() => void (state.age = 44)}></button>\n    </div>\n  )\n}\n```\n\nState can be mutated from anywhere - not just from within a component:\n\n```js\nimport { useIbiza, store } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n    </div>\n  )\n}\n\n// <App> component will re-render when this line executes, as `name` has changed.\nstore.state.name = 'Ash'\n```\n\n### Initial State\n\nYou can pass some initial state to `useIbiza` which will be merged with existing state in the Ibiza\nstore.\n\n```jsx\nconst App = () => {\n  const state = useIbiza({ user: { name: 'Joel' } })\n\n  return <h1>Hello {state.user.name}</h1>\n}\n```\n\nThis is safe to include in the body of your component, as it will only be merged into the store on\nfirst render.\n\n### Slicing\n\nIbiza supports deeply nested objects, allowing you to design the shape of your state any way you\nlike. To help you work with such nested state, the `useIbiza` hook supports slicing.\n\nThe following example assumes you have an existing state object:\n\n```javascript\n{\n  user: {\n    name: 'Joel',\n    partner: {\n      name: 'Sam',\n    }\n  }\n}\n```\n\nPass a string to `useIbiza` to fetch a specific slice of state. The string should be the path to the\nobject that you want.\n\n```jsx\nconst App = () => {\n  const partner = useIbiza('user.partner')\n\n  return (\n    <div>\n      <h1>Hello {partner.name}</h1>\n      <button onClick={() => void (partner.name = 'Bob')}></button>\n    </div>\n  )\n}\n```\n\nNote that slicing is really only supported as a convenience, and will not generally help with\nperformance.\n\n## `createModel()`\n\nIbiza is at its most powerful when working with models. They provide reusability and flexibility.\n\nCreate a model using the `createModel` helper, where the first argument is the model name, and the\nsecond argument is the initial model state as a plain object.\n\n```javascript\n// model.js\n\nexport default createModel('user', {\n  firstName: 'Joel',\n  lastName: 'Moss',\n  children: [{ firstName: 'Ash' }, { firstName: 'Elijah' }, { firstName: 'Eve' }]\n})\n```\n\n`createModel` returns a hook which you can use. You can now import your model anywhere:\n\n```jsx\n// app.jsx\n\nimport useModel from './model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <div>\n      <h1>Hello {user.firstName}</h1>\n      <ul>\n        {user.children.map((child, i) => (\n          <li key={i}>{child.firstName}</li>\n        ))}\n      </ul>\n    </div>\n  )\n}\n```\n\n### Initial State\n\nSometimes you want to be able to define your model with some initial state that could be provided\ndynamically. For example, from component props or some other parameters.\n\n`createModel` can accept a function as its second argument. This function will be called on\ninitialisation with two arguments; the current `state` and any `props` passed to it when its hook is\nfirst called.\n\n```javascript\n// model.js\n\nexport default createModel('user', (state, props) => ({\n  firstName: 'Joel',\n  lastName: 'Moss'\n  ...props\n}))\n```\n\n```jsx\n// app.jsx\n\nimport useModel from './model'\n\nconst App = ({ yearOfBirth }) => {\n  const user = useModel({ yearOfBirth })\n\n  return (\n    <div>\n      <h1>\n        Hello {user.firstName}, you were born in {user.yearOfBirth}.\n      </h1>\n    </div>\n  )\n}\n```\n\n### Functions\n\nYou can use regular function in your model. They accept the current state as the first argument, and\n`this` will also be the current state (as long as you don't use hash rocket functions).\n\n```jsx\nconst App = () => {\n  const state = useIbiza({\n    count: 0,\n    increment: state => {\n      ++state.count\n    },\n    decrement() {\n      ++this.count\n    }\n  })\n\n  return (\n    <>\n      <h1>Count = {state.count}</h1>\n      <button onClick={state.increment}>Increment</button>\n      <button onClick={state.decrement}>Decrement</button>\n    </>\n  )\n}\n```\n\nWhen reading/writing state within a function, `this` responds to the state at the level where the\nfunction sits. This means that if the function is deeply nested, `this` will not include state lower\ndown.\n\nTo solve this, you can call `this.$model` to access your model, or `this.$root` to access the root\nof the store state.\n\n```javascript\nuseIbiza({\n  deepstate: {\n    user: {\n      name: 'Joel',\n      partner: {\n        name: 'Sam',\n\n        get partner() {\n          // `this` refers to 'deepstate.user.partner'.\n          // `this.$model` refers to 'deepstate.user'.\n          // `this.$root` is the whole store state.\n          return this.$model.name\n        }\n      }\n    }\n  }\n})\n```\n\nFunctions accept any number of arguments just like regular functions do, but don't forget that the\nfirst argument is always the state.\n\n```jsx\nconst App = () => {\n  const user = useIbiza({\n    children: [],\n    addChild(state, firstName, lastName) {\n      state.children.push({ firstName, lastName }) // or `this.children.push(...)`\n    }\n  })\n\n  return (\n    <>\n      <ul>\n        {user.children.map((child, i) => (\n          <li key={i}>\n            {child.firstName} {child.lastName}\n          </li>\n        ))}\n      </ul>\n      <button onClick={() => user.addChild('Ash', 'Moss')}></button>\n    </>\n  )\n}\n```\n\nNote that used state is not tracked within functions. This avoids unnecessary component re-rendering\nwhen state changes that is used by a function. The function will always use the latest state anyway,\nso no need to track the state that it uses.\n\nThis does however, mean that you should not call functions during rendering - use a getter instead.\n\n### Getters and Setters\n\nIbiza supports Javascript getters and setters in your state and models.\n\n```javascript\nexport default createModel('user', {\n  firstName: 'Joel',\n  lastName: 'Moss',\n\n  get fullName() {\n    // You can read/write to your state via `this`.\n    return `${this.firstName} ${this.lastName}`\n  },\n\n  set fullName(value) {\n    const [firstName, lastName] = value.split(' ')\n\n    this.firstName = firstName\n    this.lastName = lastName\n  }\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <h1>Hello {user.fullName}</h1>\n      <button onClick={() => void (user.fullName = 'Bob Bones')}></button>\n    </>\n  )\n}\n```\n\n### Async Functions\n\nFunctions can be async and/or return Promises, and support React's Suspense by default.\n\n```javascript\nexport default createModel('user', {\n  name: 'Joel',\n\n  async doSomething() {\n    return await someAsyncAction()\n  }\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <h1>Hello {user.fullName}</h1>\n      <button onClick={user.doSomething}></button>\n    </>\n  )\n}\n```\n\n### URL Models\n\nBecause reading and writing to/from the server is so common, Ibiza has support to make this easy\nwith URL Models, similar to react-query. Simply use a valid and relative URL as your model name or\nslice.\n\nThe following will fetch the user from the server at `/user`, suspending the component while it does\nso. The data is fetched only when it does not exist in the store.\n\n```jsx\nconst App = () => {\n  const user = useIbiza('/user')\n\n  return <h1>Hello {user.name}</h1>\n}\n```\n\nYou can safely mutate your model, as all mutations will remain local.\n\nYou can write your model state back to the server. It the server responds with JSON, the model will\nbe updated with that response.\n\n```jsx\nconst App = () => {\n  const user = useIbiza('/user')\n\n  const renameUser = async () => {\n    await user.save({ body: { name: 'Bob' } })\n  }\n\n  return (\n    <>\n      <h1>Hello {user.name}</h1>\n      <button onClick={renameUser}></button>\n    </>\n  )\n}\n```\n\nURL Models can also be defined with `createModel`, and accept the same arguments:\n\n```javascript\nexport default createModel('/user')\n```\n\n`createModel` returns a hook which you can use. You can now import your model anywhere:\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return <h1>Hello {user.firstName}</h1>\n}\n```\n\nAdditionally, URL models accept a `fetcher` option, which when provided, will be used as the fetch\nfunction for the model:\n\n```javascript\nexport default createModel('/user', {}, { fetcher: myFetchFunction })\n```\n\n## `createContextModel()`\n\nWrap your component in the `IbizaProvider` higher order component, and instead of `createModel()`,\ncreate your model with `createContextModel()` function. The model will automatically be given a\nunique name specific to the wrapped components in IbizaProvider. Just pass the model definition as\nthe first argument. It accepts the same options as `createModel()` for the second argument.\n\n```jsx\nconst useModel = createContextModel(() => ({\n  // Your model definition...\n  name: 'Awesome!'\n}))\n\nconst App = () => {\n  return (\n    <IbizaProvider>\n      <MyComponent />\n    </IbizaProvider>\n  );\n};\n\nconst MyComponent = () => {\n  const model = useModel()\n\n  return <h1>My model is {model.name}</h1>\n};\n```\n\nEach instance of IbizaProvider will use its own state.\n\n```jsx\nconst useFirstModel = createContextModel(() => ({\n  name: 'FIRST!'\n}))\n\nconst useSecondModel = createContextModel(() => ({\n  name: 'SECOND!'\n}))\n\nconst App = () => {\n  return (\n    <>\n      <IbizaProvider>\n        <MyFirstComponent />\n      </IbizaProvider>\n      <IbizaProvider>\n        <MySecondComponent />\n      </IbizaProvider>\n    </>\n  );\n};\n\nconst MyFirstComponent = () => {\n  const model = useFirstModel();\n\n  return <h1>My model is {model.name}</h1>; // My model is FIRST!\n};\n\nconst MySecondComponent = () => {\n  const model = useSecondModel()\n\n  return <h1>My model is {model.name}</h1> // My model is SECOND!\n};\n```\n\n","readmeFilename":"README.md","_id":"ibiza@2.0.0-alpha.3","_integrity":"sha512-w0PBeCQhvm0VDlO1R3CWWrGHP19twOTvlkIsvPGpfEkA4BfvKuRxazHpVmQUpx/abVdncWtD+J6BA6JhY/bM7w==","_resolved":"/private/var/folders/3b/b6pthvr51cg1755k2jxx8www0000gn/T/026cc47fab751f8aae15f39e962ec2f1/ibiza-2.0.0-alpha.3.tgz","_from":"file:ibiza-2.0.0-alpha.3.tgz","_nodeVersion":"18.4.0","_npmVersion":"8.12.1","dist":{"integrity":"sha512-w0PBeCQhvm0VDlO1R3CWWrGHP19twOTvlkIsvPGpfEkA4BfvKuRxazHpVmQUpx/abVdncWtD+J6BA6JhY/bM7w==","shasum":"1cb89fc2c9dca1f70e302a34d9affd0937feee36","tarball":"https://registry.npmjs.org/ibiza/-/ibiza-2.0.0-alpha.3.tgz","fileCount":10,"unpackedSize":319274,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGkndCcqoDZmlE6ldY7/nhQkg9X5g6dvDrssVylWy+eUAiArQkQKV/NHWOcqaI7GJlQCjwDrQiFDJAdRQCmfEtBRMg=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiuw65ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrwaQ/5AWu+QvSMnr82X2yHAAVuNm4ey1E5fR9SWBmuNr+emMci5rux\r\nVTn2Pqed2+nDiwJ2RutiyFTTJq3JOpEe8OQMgjUBFFs/a4ORqFwN3A76MWFP\r\ng/cbE8rrNhMr3chBxm1kyzlDzeEJnefVeQ1tL1xPulmi2AC91K3GnhV8E/vu\r\nqX8sBIGqu0SgcPig+ClQDlnv0+BnQT+1ZdlEGLkGP7kqW6b2Yc82xLxIMcc5\r\nhE0HXHYEw8u01KAt0aLve4whErNMBPpHbXjGEQYk1obMJ0BUlSLdYU3Nmxa2\r\nQA/by6f6ubb1VBZTjTAzB2uP5ybUpE1yXv0/Isr43Z1oNX5Axx6r9q51YdK9\r\n/B/3PA4wT1lZFxiL7Si04B7yYn4hTQgpEmymt2Sx6EjJsxCmShc+xVVA1COS\r\nBIr+bXx0yhPAEh7vV3g5+gS+6XKwZL4dt24ekUiFYhqlNb4W/q8qJbNjX5lP\r\nvRG6E4mMeN6SbkZDSJTan52gvXwLk7ZnznYV3/3ljbFaa9XvC/nQB7sFjibB\r\nwAxAXsYlRAcPeKz9fggVXT+Dy1qDbu8ylQ6qQqt6w9Ora+dkQ5d0h7PRB0+G\r\n6idGUGnsA9fyRluWbT6LTG4i6rUuQ3CWxO2HuKrm9J0q0iW/hdC0qYDsc3s8\r\n15wPDpJBbV/B0PkesJl1Pj8eou7yXwe2tSg=\r\n=xxBW\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"joelmoss","email":"joel@developwithstyle.com"},"directories":{},"maintainers":[{"name":"joelmoss","email":"joel@developwithstyle.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ibiza_2.0.0-alpha.3_1656426168949_0.35763142094086287"},"_hasShrinkwrap":false},"2.0.0-alpha.4":{"name":"ibiza","author":{"name":"Joel Moss"},"version":"2.0.0-alpha.4","description":"React State Management for Party Animals","license":"MIT","homepage":"https://github.com/joelmoss/ibiza","repository":{"type":"git","url":"git+https://github.com/joelmoss/ibiza.git"},"bugs":{"url":"https://github.com/joelmoss/ibiza/issues"},"keywords":["react","state","proxy"],"type":"module","source":"src/index.js","main":"dist/ibiza.cjs","module":"dist/ibiza.module.js","unpkg":"dist/ibiza.umd.js","exports":{"require":"./dist/ibiza.cjs","default":"./dist/ibiza.modern.js"},"sideEffects":false,"eslintConfig":{"extends":["eslint:recommended","plugin:react/recommended","plugin:react-hooks/recommended","plugin:prettier/recommended"],"settings":{"react":{"version":"detect"}},"env":{"browser":true,"node":false,"es6":true},"parserOptions":{"ecmaVersion":"latest","sourceType":"module","ecmaFeatures":{"jsx":true}},"rules":{"react/prop-types":0},"overrides":[{"files":["test/**"],"extends":["plugin:jest/recommended","plugin:testing-library/react","plugin:jest/style"],"rules":{"jest/expect-expect":["warn",{"assertFunctionNames":["expect","screen.findByText","screen.getByText"]}]}}]},"size-limit":[{"name":"useIbiza","path":"./src/index.js","import":"{ useIbiza }","limit":"1 s"},{"name":"store","path":"./src/index.js","import":"{ store }","limit":"1 s"},{"name":"createModel","path":"./src/index.js","import":"{ createModel }","limit":"1 s"},{"name":"rawStateOf","path":"./src/index.js","import":"{ rawStateOf }","limit":"1 s"},{"name":"freeze","path":"./src/index.js","import":"{ freeze }","limit":"1 s"}],"prettier":{"trailingComma":"none","printWidth":100,"semi":false,"singleQuote":true,"arrowParens":"avoid"},"peerDependencies":{"react":">=17"},"devDependencies":{"@size-limit/preset-big-lib":"^7.0.1","@swc/core":"^1.2.144","@swc/jest":"^0.2.17","@testing-library/jest-dom":"^5.15.0","@testing-library/react":"^13.0.0","cross-fetch":"^3.1.4","eslint":"^8.18.0","eslint-config-prettier":"^8.5.0","eslint-plugin-jest":"^26.5.3","eslint-plugin-prettier":"^4.0.0","eslint-plugin-react":"^7.30.0","eslint-plugin-react-hooks":"^4.6.0","eslint-plugin-testing-library":"^5.5.1","fetch-mock-jest":"^1.5.1","ibiza":"link:./ibiza","jest":"^28.1.0","jest-environment-jsdom":"^28.1.0","microbundle":"^0.15.0","msw":"^0.42","prettier":"^2.7.1","react":"^18.2.0","react-dom":"^18.2.0","react-error-boundary":"^3.1.4","rimraf":"^3.0.2","size-limit":"^7.0.0"},"dependencies":{"fast-equals":"^4.0.0","micro-memoize":"^4.0.9","use-sync-external-store":"^1.2.0"},"scripts":{"clean":"rimraf dist","test":"jest","build":"microbundle --jsx React.createElement","dev":"microbundle watch --jsx React.createElement --compress false","size":"microbundle && size-limit","lint":"eslint src test --ext .jsx --ext .js"},"readme":"# Ibiza - React State Management for Party Animals\n\nIbiza gets out of your way and simply lets you read and write state as you would with regular\nJavascript assignment. It maintains a global state object and is smart enough to know when to\nrerender your components based on state usage and modification.\n\n## `useIbiza()` ✨\n\nA component calls the `useIbiza` React hook, which returns the store state as a JS Proxy object.\nThis Proxy records when a state property is accessed or \"used\". Then when that property is mutated,\nthe component is rerendered.\n\nThis means that you can mutate your state in any way, but your component will only rerender if you\nmutate state that you have used.\n\nThe following component will rerender when the button is clicked, because `name` has changed.\n\n```jsx\nimport { useIbiza } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n      <button onClick={() => void (state.name = 'Joel')}></button>\n    </div>\n  )\n}\n```\n\nThe following component will not rerender when the button is clicked, because even though `age` has\nbeen mutated, it is not actually being used within the component.\n\n```jsx\nimport { useIbiza } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n      <button onClick={() => void (state.age = 44)}></button>\n    </div>\n  )\n}\n```\n\nState can be mutated from anywhere - not just from within a component:\n\n```js\nimport { useIbiza, store } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n    </div>\n  )\n}\n\n// <App> component will re-render when this line executes, as `name` has changed.\nstore.state.name = 'Ash'\n```\n\n### Initial State\n\nYou can pass some initial state to `useIbiza` which will be merged with existing state in the Ibiza\nstore.\n\n```jsx\nconst App = () => {\n  const state = useIbiza({ user: { name: 'Joel' } })\n\n  return <h1>Hello {state.user.name}</h1>\n}\n```\n\nThis is safe to include in the body of your component, as it will only be merged into the store on\nfirst render.\n\n### Slicing\n\nIbiza supports deeply nested objects, allowing you to design the shape of your state any way you\nlike. To help you work with such nested state, the `useIbiza` hook supports slicing.\n\nThe following example assumes you have an existing state object:\n\n```javascript\n{\n  user: {\n    name: 'Joel',\n    partner: {\n      name: 'Sam',\n    }\n  }\n}\n```\n\nPass a string to `useIbiza` to fetch a specific slice of state. The string should be the path to the\nobject that you want.\n\n```jsx\nconst App = () => {\n  const partner = useIbiza('user.partner')\n\n  return (\n    <div>\n      <h1>Hello {partner.name}</h1>\n      <button onClick={() => void (partner.name = 'Bob')}></button>\n    </div>\n  )\n}\n```\n\nNote that slicing is really only supported as a convenience, and will not generally help with\nperformance.\n\n## `createModel()`\n\nIbiza is at its most powerful when working with models. They provide reusability and flexibility.\n\nCreate a model using the `createModel` helper, where the first argument is the model name, and the\nsecond argument is the initial model state as a plain object.\n\n```javascript\n// model.js\n\nexport default createModel('user', {\n  firstName: 'Joel',\n  lastName: 'Moss',\n  children: [{ firstName: 'Ash' }, { firstName: 'Elijah' }, { firstName: 'Eve' }]\n})\n```\n\n`createModel` returns a hook which you can use. You can now import your model anywhere:\n\n```jsx\n// app.jsx\n\nimport useModel from './model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <div>\n      <h1>Hello {user.firstName}</h1>\n      <ul>\n        {user.children.map((child, i) => (\n          <li key={i}>{child.firstName}</li>\n        ))}\n      </ul>\n    </div>\n  )\n}\n```\n\n### Initial State\n\nSometimes you want to be able to define your model with some initial state that could be provided\ndynamically. For example, from component props or some other parameters.\n\n`createModel` can accept a function as its second argument. This function will be called on\ninitialisation with two arguments; the current `state` and any `props` passed to it when its hook is\nfirst called.\n\n```javascript\n// model.js\n\nexport default createModel('user', (state, props) => ({\n  firstName: 'Joel',\n  lastName: 'Moss'\n  ...props\n}))\n```\n\n```jsx\n// app.jsx\n\nimport useModel from './model'\n\nconst App = ({ yearOfBirth }) => {\n  const user = useModel({ yearOfBirth })\n\n  return (\n    <div>\n      <h1>\n        Hello {user.firstName}, you were born in {user.yearOfBirth}.\n      </h1>\n    </div>\n  )\n}\n```\n\n### Functions\n\nYou can use regular function in your model. They accept the current state as the first argument, and\n`this` will also be the current state (as long as you don't use hash rocket functions).\n\n```jsx\nconst App = () => {\n  const state = useIbiza({\n    count: 0,\n    increment: state => {\n      ++state.count\n    },\n    decrement() {\n      ++this.count\n    }\n  })\n\n  return (\n    <>\n      <h1>Count = {state.count}</h1>\n      <button onClick={state.increment}>Increment</button>\n      <button onClick={state.decrement}>Decrement</button>\n    </>\n  )\n}\n```\n\nWhen reading/writing state within a function, `this` responds to the state at the level where the\nfunction sits. This means that if the function is deeply nested, `this` will not include state lower\ndown.\n\nTo solve this, you can call `this.$model` to access your model, or `this.$root` to access the root\nof the store state.\n\n```javascript\nuseIbiza({\n  deepstate: {\n    user: {\n      name: 'Joel',\n      partner: {\n        name: 'Sam',\n\n        get partner() {\n          // `this` refers to 'deepstate.user.partner'.\n          // `this.$model` refers to 'deepstate.user'.\n          // `this.$root` is the whole store state.\n          return this.$model.name\n        }\n      }\n    }\n  }\n})\n```\n\nFunctions accept any number of arguments just like regular functions do, but don't forget that the\nfirst argument is always the state.\n\n```jsx\nconst App = () => {\n  const user = useIbiza({\n    children: [],\n    addChild(state, firstName, lastName) {\n      state.children.push({ firstName, lastName }) // or `this.children.push(...)`\n    }\n  })\n\n  return (\n    <>\n      <ul>\n        {user.children.map((child, i) => (\n          <li key={i}>\n            {child.firstName} {child.lastName}\n          </li>\n        ))}\n      </ul>\n      <button onClick={() => user.addChild('Ash', 'Moss')}></button>\n    </>\n  )\n}\n```\n\nNote that used state is not tracked within functions. This avoids unnecessary component re-rendering\nwhen state changes that is used by a function. The function will always use the latest state anyway,\nso no need to track the state that it uses.\n\nThis does however, mean that you should not call functions during rendering - use a getter instead.\n\n### Getters and Setters\n\nIbiza supports Javascript getters and setters in your state and models.\n\n```javascript\nexport default createModel('user', {\n  firstName: 'Joel',\n  lastName: 'Moss',\n\n  get fullName() {\n    // You can read/write to your state via `this`.\n    return `${this.firstName} ${this.lastName}`\n  },\n\n  set fullName(value) {\n    const [firstName, lastName] = value.split(' ')\n\n    this.firstName = firstName\n    this.lastName = lastName\n  }\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <h1>Hello {user.fullName}</h1>\n      <button onClick={() => void (user.fullName = 'Bob Bones')}></button>\n    </>\n  )\n}\n```\n\n### Async Functions\n\nFunctions can be async and/or return Promises, and support React's Suspense by default.\n\n```javascript\nexport default createModel('user', {\n  name: 'Joel',\n\n  async doSomething() {\n    return await someAsyncAction()\n  }\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <h1>Hello {user.fullName}</h1>\n      <button onClick={user.doSomething}></button>\n    </>\n  )\n}\n```\n\n### URL Models\n\nBecause reading and writing to/from the server is so common, Ibiza has support to make this easy\nwith URL Models, similar to react-query. Simply use a valid and relative URL as your model name or\nslice.\n\nThe following will fetch the user from the server at `/user`, suspending the component while it does\nso. The data is fetched only when it does not exist in the store.\n\n```jsx\nconst App = () => {\n  const user = useIbiza('/user')\n\n  return <h1>Hello {user.name}</h1>\n}\n```\n\nYou can safely mutate your model, as all mutations will remain local.\n\nYou can write your model state back to the server. It the server responds with JSON, the model will\nbe updated with that response.\n\n```jsx\nconst App = () => {\n  const user = useIbiza('/user')\n\n  const renameUser = async () => {\n    await user.save({ body: { name: 'Bob' } })\n  }\n\n  return (\n    <>\n      <h1>Hello {user.name}</h1>\n      <button onClick={renameUser}></button>\n    </>\n  )\n}\n```\n\nURL Models can also be defined with `createModel`, and accept the same arguments:\n\n```javascript\nexport default createModel('/user')\n```\n\n`createModel` returns a hook which you can use. You can now import your model anywhere:\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return <h1>Hello {user.firstName}</h1>\n}\n```\n\nAdditionally, URL models accept a `fetcher` option, which when provided, will be used as the fetch\nfunction for the model:\n\n```javascript\nexport default createModel('/user', {}, { fetcher: myFetchFunction })\n```\n\n## `createContextModel()`\n\nWrap your component in the `IbizaProvider` higher order component, and instead of `createModel()`,\ncreate your model with `createContextModel()` function. The model will automatically be given a\nunique name specific to the wrapped components in IbizaProvider. Just pass the model definition as\nthe first argument. It accepts the same options as `createModel()` for the second argument.\n\n```jsx\nconst useModel = createContextModel(() => ({\n  // Your model definition...\n  name: 'Awesome!'\n}))\n\nconst App = () => {\n  return (\n    <IbizaProvider>\n      <MyComponent />\n    </IbizaProvider>\n  );\n};\n\nconst MyComponent = () => {\n  const model = useModel()\n\n  return <h1>My model is {model.name}</h1>\n};\n```\n\nEach instance of IbizaProvider will use its own state.\n\n```jsx\nconst useFirstModel = createContextModel(() => ({\n  name: 'FIRST!'\n}))\n\nconst useSecondModel = createContextModel(() => ({\n  name: 'SECOND!'\n}))\n\nconst App = () => {\n  return (\n    <>\n      <IbizaProvider>\n        <MyFirstComponent />\n      </IbizaProvider>\n      <IbizaProvider>\n        <MySecondComponent />\n      </IbizaProvider>\n    </>\n  );\n};\n\nconst MyFirstComponent = () => {\n  const model = useFirstModel();\n\n  return <h1>My model is {model.name}</h1>; // My model is FIRST!\n};\n\nconst MySecondComponent = () => {\n  const model = useSecondModel()\n\n  return <h1>My model is {model.name}</h1> // My model is SECOND!\n};\n```\n\n","readmeFilename":"README.md","_id":"ibiza@2.0.0-alpha.4","_integrity":"sha512-CJD+WMlhY824J6slv0icWEMuc4JtleGaLqDqfvcI3PuwuxFblI5exjiT89cqThVGFD7g96OniNdiyfLFXngLvA==","_resolved":"/private/var/folders/3b/b6pthvr51cg1755k2jxx8www0000gn/T/71026d7aa433eb0aee3932f79d4984cb/ibiza-2.0.0-alpha.4.tgz","_from":"file:ibiza-2.0.0-alpha.4.tgz","_nodeVersion":"18.4.0","_npmVersion":"8.12.1","dist":{"integrity":"sha512-CJD+WMlhY824J6slv0icWEMuc4JtleGaLqDqfvcI3PuwuxFblI5exjiT89cqThVGFD7g96OniNdiyfLFXngLvA==","shasum":"8edd0697e394fcfd735112f5429ce94ffdde070e","tarball":"https://registry.npmjs.org/ibiza/-/ibiza-2.0.0-alpha.4.tgz","fileCount":10,"unpackedSize":319385,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC/nLaamV0sliGpcEkazY69kAcyp21hbdlW4VnOPdjBDAIgEx2n+GQAH+OdvID6aiRhBYmbNIdX7JilfhStBKw+X7c="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiuyY9ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqGNw/+NwW5gOLVYGVXNe3JuypI/Yk1FdCsOXA0cO63AFr4rcl0Xo2t\r\nguLoOPuOgl0BKu5Pl6GUcBceJ2X86ZzIZhCu09XsyF69q/P8jQG0sbGTiG8W\r\n6P06gy3zjavoxCd5YpqpudvjO+MjROZFkPtqcpubKE6EeSdzGA1OroGuxEhD\r\n/NSB1TnS6mYQLSNFYrm/RV0JDbwS8Mk9QED1iSkhW20IlGmK0A7c3pNY53+8\r\nDg5uyvdCwZH9GYzKEXp/NMHHSMJdRZWMJxHc7il4yictfD/iCs1TirXZT2T5\r\nltAcuc6istpoVXU3DwDl0YxTWchyA10sUaXBzQZ4L16gEwf+yqiQGraGLf9o\r\nOPGov40ffL4CBgR18h8iGk292PyQyQJqNcH3cnZedkpB4VIPps3heZwNCE1I\r\n/kgsOO/dkUq0bsCM+6+BvuP00MEvydLs7rperk3DfbM0UtMci/kMIAOK/Nz7\r\noh0M2xRT8j7Pvqw/zrsxJi1nQza7f8VJKIoryko8PH34djpp+ggH5yf1W4tq\r\n31PNTyZz3h+c9qP35ECZkfaCP3Ufetu3zG+X3O7gM15BXMOQcXSiOuG9kX2j\r\njP6eu77VWVYAs3eJ7V5AmOg159DtcavJGuBJ3+JmbFW0bZKoIgT/u87z86z5\r\niJOkKhQtkBW8BJ+2EjcEhUowtb2LjIJY7r0=\r\n=68D6\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"joelmoss","email":"joel@developwithstyle.com"},"directories":{},"maintainers":[{"name":"joelmoss","email":"joel@developwithstyle.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ibiza_2.0.0-alpha.4_1656432188788_0.6424228508995005"},"_hasShrinkwrap":false},"2.0.0-alpha.5":{"name":"ibiza","author":{"name":"Joel Moss"},"version":"2.0.0-alpha.5","description":"React State Management for Party Animals","license":"MIT","homepage":"https://github.com/joelmoss/ibiza","repository":{"type":"git","url":"git+https://github.com/joelmoss/ibiza.git"},"bugs":{"url":"https://github.com/joelmoss/ibiza/issues"},"keywords":["react","state","proxy"],"type":"module","source":"src/index.js","main":"dist/ibiza.cjs","module":"dist/ibiza.module.js","unpkg":"dist/ibiza.umd.js","exports":{"require":"./dist/ibiza.cjs","default":"./dist/ibiza.modern.js"},"sideEffects":false,"eslintConfig":{"extends":["eslint:recommended","plugin:react/recommended","plugin:react-hooks/recommended","plugin:prettier/recommended"],"settings":{"react":{"version":"detect"}},"env":{"browser":true,"node":false,"es6":true},"parserOptions":{"ecmaVersion":"latest","sourceType":"module","ecmaFeatures":{"jsx":true}},"rules":{"react/prop-types":0},"overrides":[{"files":["test/**"],"extends":["plugin:jest/recommended","plugin:testing-library/react","plugin:jest/style"],"rules":{"jest/expect-expect":["warn",{"assertFunctionNames":["expect","screen.findByText","screen.getByText"]}]}}]},"size-limit":[{"name":"useIbiza","path":"./src/index.js","import":"{ useIbiza }","limit":"1 s"},{"name":"store","path":"./src/index.js","import":"{ store }","limit":"1 s"},{"name":"createModel","path":"./src/index.js","import":"{ createModel }","limit":"1 s"},{"name":"rawStateOf","path":"./src/index.js","import":"{ rawStateOf }","limit":"1 s"},{"name":"freeze","path":"./src/index.js","import":"{ freeze }","limit":"1 s"}],"prettier":{"trailingComma":"none","printWidth":100,"semi":false,"singleQuote":true,"arrowParens":"avoid"},"peerDependencies":{"react":">=17"},"devDependencies":{"@size-limit/preset-big-lib":"^7.0.1","@swc/core":"^1.2.144","@swc/jest":"^0.2.17","@testing-library/jest-dom":"^5.15.0","@testing-library/react":"^13.0.0","cross-fetch":"^3.1.4","eslint":"^8.18.0","eslint-config-prettier":"^8.5.0","eslint-plugin-jest":"^26.5.3","eslint-plugin-prettier":"^4.0.0","eslint-plugin-react":"^7.30.0","eslint-plugin-react-hooks":"^4.6.0","eslint-plugin-testing-library":"^5.5.1","fetch-mock-jest":"^1.5.1","ibiza":"link:./ibiza","jest":"^28.1.0","jest-environment-jsdom":"^28.1.0","microbundle":"^0.15.0","msw":"^0.42","prettier":"^2.7.1","react":"^18.2.0","react-dom":"^18.2.0","react-error-boundary":"^3.1.4","rimraf":"^3.0.2","size-limit":"^7.0.0"},"dependencies":{"fast-equals":"^4.0.0","micro-memoize":"^4.0.9","use-sync-external-store":"^1.2.0"},"scripts":{"clean":"rimraf dist","test":"jest","build":"microbundle --jsx React.createElement","dev":"microbundle watch --jsx React.createElement --compress false","size":"microbundle && size-limit","lint":"eslint src test --ext .jsx --ext .js"},"readme":"# Ibiza - React State Management for Party Animals\n\nIbiza gets out of your way and simply lets you read and write state as you would with regular\nJavascript assignment. It maintains a global state object and is smart enough to know when to\nrerender your components based on state usage and modification.\n\n## `useIbiza()` ✨\n\nA component calls the `useIbiza` React hook, which returns the store state as a JS Proxy object.\nThis Proxy records when a state property is accessed or \"used\". Then when that property is mutated,\nthe component is rerendered.\n\nThis means that you can mutate your state in any way, but your component will only rerender if you\nmutate state that you have used.\n\nThe following component will rerender when the button is clicked, because `name` has changed.\n\n```jsx\nimport { useIbiza } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n      <button onClick={() => void (state.name = 'Joel')}></button>\n    </div>\n  )\n}\n```\n\nThe following component will not rerender when the button is clicked, because even though `age` has\nbeen mutated, it is not actually being used within the component.\n\n```jsx\nimport { useIbiza } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n      <button onClick={() => void (state.age = 44)}></button>\n    </div>\n  )\n}\n```\n\nState can be mutated from anywhere - not just from within a component:\n\n```js\nimport { useIbiza, store } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n    </div>\n  )\n}\n\n// <App> component will re-render when this line executes, as `name` has changed.\nstore.state.name = 'Ash'\n```\n\n### Initial State\n\nYou can pass some initial state to `useIbiza` which will be merged with existing state in the Ibiza\nstore.\n\n```jsx\nconst App = () => {\n  const state = useIbiza({ user: { name: 'Joel' } })\n\n  return <h1>Hello {state.user.name}</h1>\n}\n```\n\nThis is safe to include in the body of your component, as it will only be merged into the store on\nfirst render.\n\n### Slicing\n\nIbiza supports deeply nested objects, allowing you to design the shape of your state any way you\nlike. To help you work with such nested state, the `useIbiza` hook supports slicing.\n\nThe following example assumes you have an existing state object:\n\n```javascript\n{\n  user: {\n    name: 'Joel',\n    partner: {\n      name: 'Sam',\n    }\n  }\n}\n```\n\nPass a string to `useIbiza` to fetch a specific slice of state. The string should be the path to the\nobject that you want.\n\n```jsx\nconst App = () => {\n  const partner = useIbiza('user.partner')\n\n  return (\n    <div>\n      <h1>Hello {partner.name}</h1>\n      <button onClick={() => void (partner.name = 'Bob')}></button>\n    </div>\n  )\n}\n```\n\nNote that slicing is really only supported as a convenience, and will not generally help with\nperformance.\n\n## `createModel()`\n\nIbiza is at its most powerful when working with models. They provide reusability and flexibility.\n\nCreate a model using the `createModel` helper, where the first argument is the model name, and the\nsecond argument is the initial model state as a plain object.\n\n```javascript\n// model.js\n\nexport default createModel('user', {\n  firstName: 'Joel',\n  lastName: 'Moss',\n  children: [{ firstName: 'Ash' }, { firstName: 'Elijah' }, { firstName: 'Eve' }]\n})\n```\n\n`createModel` returns a hook which you can use. You can now import your model anywhere:\n\n```jsx\n// app.jsx\n\nimport useModel from './model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <div>\n      <h1>Hello {user.firstName}</h1>\n      <ul>\n        {user.children.map((child, i) => (\n          <li key={i}>{child.firstName}</li>\n        ))}\n      </ul>\n    </div>\n  )\n}\n```\n\n### Initial State\n\nSometimes you want to be able to define your model with some initial state that could be provided\ndynamically. For example, from component props or some other parameters.\n\n`createModel` can accept a function as its second argument. This function will be called on\ninitialisation with two arguments; the current `state` and any `props` passed to it when its hook is\nfirst called.\n\n```javascript\n// model.js\n\nexport default createModel('user', (state, props) => ({\n  firstName: 'Joel',\n  lastName: 'Moss'\n  ...props\n}))\n```\n\n```jsx\n// app.jsx\n\nimport useModel from './model'\n\nconst App = ({ yearOfBirth }) => {\n  const user = useModel({ yearOfBirth })\n\n  return (\n    <div>\n      <h1>\n        Hello {user.firstName}, you were born in {user.yearOfBirth}.\n      </h1>\n    </div>\n  )\n}\n```\n\n### Functions\n\nYou can use regular function in your model. They accept the current state as the first argument, and\n`this` will also be the current state (as long as you don't use hash rocket functions).\n\n```jsx\nconst App = () => {\n  const state = useIbiza({\n    count: 0,\n    increment: state => {\n      ++state.count\n    },\n    decrement() {\n      ++this.count\n    }\n  })\n\n  return (\n    <>\n      <h1>Count = {state.count}</h1>\n      <button onClick={state.increment}>Increment</button>\n      <button onClick={state.decrement}>Decrement</button>\n    </>\n  )\n}\n```\n\nWhen reading/writing state within a function, `this` responds to the state at the level where the\nfunction sits. This means that if the function is deeply nested, `this` will not include state lower\ndown.\n\nTo solve this, you can call `this.$model` to access your model, or `this.$root` to access the root\nof the store state.\n\n```javascript\nuseIbiza({\n  deepstate: {\n    user: {\n      name: 'Joel',\n      partner: {\n        name: 'Sam',\n\n        get partner() {\n          // `this` refers to 'deepstate.user.partner'.\n          // `this.$model` refers to 'deepstate.user'.\n          // `this.$root` is the whole store state.\n          return this.$model.name\n        }\n      }\n    }\n  }\n})\n```\n\nFunctions accept any number of arguments just like regular functions do, but don't forget that the\nfirst argument is always the state.\n\n```jsx\nconst App = () => {\n  const user = useIbiza({\n    children: [],\n    addChild(state, firstName, lastName) {\n      state.children.push({ firstName, lastName }) // or `this.children.push(...)`\n    }\n  })\n\n  return (\n    <>\n      <ul>\n        {user.children.map((child, i) => (\n          <li key={i}>\n            {child.firstName} {child.lastName}\n          </li>\n        ))}\n      </ul>\n      <button onClick={() => user.addChild('Ash', 'Moss')}></button>\n    </>\n  )\n}\n```\n\nNote that used state is not tracked within functions. This avoids unnecessary component re-rendering\nwhen state changes that is used by a function. The function will always use the latest state anyway,\nso no need to track the state that it uses.\n\nThis does however, mean that you should not call functions during rendering - use a getter instead.\n\n### Getters and Setters\n\nIbiza supports Javascript getters and setters in your state and models.\n\n```javascript\nexport default createModel('user', {\n  firstName: 'Joel',\n  lastName: 'Moss',\n\n  get fullName() {\n    // You can read/write to your state via `this`.\n    return `${this.firstName} ${this.lastName}`\n  },\n\n  set fullName(value) {\n    const [firstName, lastName] = value.split(' ')\n\n    this.firstName = firstName\n    this.lastName = lastName\n  }\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <h1>Hello {user.fullName}</h1>\n      <button onClick={() => void (user.fullName = 'Bob Bones')}></button>\n    </>\n  )\n}\n```\n\n### Async Functions\n\nFunctions can be async and/or return Promises, and support React's Suspense by default.\n\n```javascript\nexport default createModel('user', {\n  name: 'Joel',\n\n  async doSomething() {\n    return await someAsyncAction()\n  }\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <h1>Hello {user.fullName}</h1>\n      <button onClick={user.doSomething}></button>\n    </>\n  )\n}\n```\n\n### URL Models\n\nBecause reading and writing to/from the server is so common, Ibiza has support to make this easy\nwith URL Models, similar to react-query. Simply use a valid and relative URL as your model name or\nslice.\n\nThe following will fetch the user from the server at `/user`, suspending the component while it does\nso. The data is fetched only when it does not exist in the store.\n\n```jsx\nconst App = () => {\n  const user = useIbiza('/user')\n\n  return <h1>Hello {user.name}</h1>\n}\n```\n\nYou can safely mutate your model, as all mutations will remain local.\n\nYou can write your model state back to the server. It the server responds with JSON, the model will\nbe updated with that response.\n\n```jsx\nconst App = () => {\n  const user = useIbiza('/user')\n\n  const renameUser = async () => {\n    await user.save({ body: { name: 'Bob' } })\n  }\n\n  return (\n    <>\n      <h1>Hello {user.name}</h1>\n      <button onClick={renameUser}></button>\n    </>\n  )\n}\n```\n\nURL Models can also be defined with `createModel`, and accept the same arguments:\n\n```javascript\nexport default createModel('/user')\n```\n\n`createModel` returns a hook which you can use. You can now import your model anywhere:\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return <h1>Hello {user.firstName}</h1>\n}\n```\n\nAdditionally, URL models accept a `fetcher` option, which when provided, will be used as the fetch\nfunction for the model:\n\n```javascript\nexport default createModel('/user', {}, { fetcher: myFetchFunction })\n```\n\n## `createContextModel()`\n\nWrap your component in the `IbizaProvider` higher order component, and instead of `createModel()`,\ncreate your model with `createContextModel()` function. The model will automatically be given a\nunique name specific to the wrapped components in IbizaProvider. Just pass the model definition as\nthe first argument. It accepts the same options as `createModel()` for the second argument.\n\n```jsx\nconst useModel = createContextModel(() => ({\n  // Your model definition...\n  name: 'Awesome!'\n}))\n\nconst App = () => {\n  return (\n    <IbizaProvider>\n      <MyComponent />\n    </IbizaProvider>\n  );\n};\n\nconst MyComponent = () => {\n  const model = useModel()\n\n  return <h1>My model is {model.name}</h1>\n};\n```\n\nEach instance of IbizaProvider will use its own state.\n\n```jsx\nconst useFirstModel = createContextModel(() => ({\n  name: 'FIRST!'\n}))\n\nconst useSecondModel = createContextModel(() => ({\n  name: 'SECOND!'\n}))\n\nconst App = () => {\n  return (\n    <>\n      <IbizaProvider>\n        <MyFirstComponent />\n      </IbizaProvider>\n      <IbizaProvider>\n        <MySecondComponent />\n      </IbizaProvider>\n    </>\n  );\n};\n\nconst MyFirstComponent = () => {\n  const model = useFirstModel();\n\n  return <h1>My model is {model.name}</h1>; // My model is FIRST!\n};\n\nconst MySecondComponent = () => {\n  const model = useSecondModel()\n\n  return <h1>My model is {model.name}</h1> // My model is SECOND!\n};\n```\n\n","readmeFilename":"README.md","_id":"ibiza@2.0.0-alpha.5","_integrity":"sha512-oYfT+bRlxqGx+r32KtskYyDGldokREYHreLelt6DUC4f5G1ZEvACZ/IR0mR2ca/t7j69+wLNCjIRk5cBMI81yw==","_resolved":"/private/var/folders/3b/b6pthvr51cg1755k2jxx8www0000gn/T/f5ec48b0bce88881519932a23ec14774/ibiza-2.0.0-alpha.5.tgz","_from":"file:ibiza-2.0.0-alpha.5.tgz","_nodeVersion":"18.4.0","_npmVersion":"8.12.1","dist":{"integrity":"sha512-oYfT+bRlxqGx+r32KtskYyDGldokREYHreLelt6DUC4f5G1ZEvACZ/IR0mR2ca/t7j69+wLNCjIRk5cBMI81yw==","shasum":"34f392680b0a30346400388b9c2a1d6ed000cdfe","tarball":"https://registry.npmjs.org/ibiza/-/ibiza-2.0.0-alpha.5.tgz","fileCount":10,"unpackedSize":319457,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBbrD2YDQjgWTUz9DchnSqHsK7lYLfWdaBBVvZtKM3H8AiEA7OWS1szgAgBREXFh1cGbnVap9mAeTJFY9Db8to86FNg="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiuy3nACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrmcA/5AYl4IiXuIpEHRVS0fXg77gl74oRYzi/KgvquT0lyaX3wJyvR\r\n7vscHHRNzm7S7y2mPIHLRW+XbZ5Ig5DyGEiYeqpRS9JDGe4S1qHHyuBCmX7E\r\nd9wjdRxl1SgIpcYB4yoGuX50ce4HIz7DHP/8yraNKdoUXk5727u8hj3qbhnK\r\nytiVOchs413GEiLQFehPoZ4/uigm+DL0nI9Kmzoxp05EuO8D/l2O7wq2SP50\r\nsZsgdgCuHZBf/pMry0ZfrlSHm7twFelQvbni0c74bEVdvOGz5OVxtzjMowxQ\r\nJk3Bfh+f2MX8tpEVcSAFTymLlngtpXLUnIc+Y6GcqQHiDLe6iI/Z+1FPUVmW\r\nYmmSaIiolMOLUH+aFxObHazJQau62cstPyiUTQU697cu3CU0JTabR2DxQv9y\r\nKpBuJ4ty+FpwX7k5lZ+NNNf330wo9zqIOtUxKlCkvIFGsc9qz/wd/wlQrkUw\r\nDpcgSZ+T9/QvmGCHtMEB3eVAeZJE+18gV3zhrRFS11acJeWjgom2I5eKpulR\r\nVL9setr55v9vB/vMtV0Bt5EEinNCJReKUL4K3K7Io8GuesbdAL0JjG3lareY\r\nelsWhbM7NPiU5n5SenTvSp2XRGNmYUlSZjBQhKa/o9+x3CFBa8DJnnm+0ycf\r\n/2HUIxZ/0YacT6wDjuCh7lNntL8iv0IICHs=\r\n=aUoz\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"joelmoss","email":"joel@developwithstyle.com"},"directories":{},"maintainers":[{"name":"joelmoss","email":"joel@developwithstyle.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ibiza_2.0.0-alpha.5_1656434151751_0.25017590048577865"},"_hasShrinkwrap":false},"2.0.0-alpha.6":{"name":"ibiza","author":{"name":"Joel Moss"},"version":"2.0.0-alpha.6","description":"React State Management for Party Animals","license":"MIT","homepage":"https://github.com/joelmoss/ibiza","repository":{"type":"git","url":"git+https://github.com/joelmoss/ibiza.git"},"bugs":{"url":"https://github.com/joelmoss/ibiza/issues"},"keywords":["react","state","proxy"],"type":"module","source":"src/index.js","main":"dist/ibiza.cjs","module":"dist/ibiza.module.js","unpkg":"dist/ibiza.umd.js","exports":{"require":"./dist/ibiza.cjs","default":"./dist/ibiza.modern.js"},"sideEffects":false,"eslintConfig":{"extends":["eslint:recommended","plugin:react/recommended","plugin:react-hooks/recommended","plugin:prettier/recommended"],"settings":{"react":{"version":"detect"}},"env":{"browser":true,"node":false,"es6":true},"parserOptions":{"ecmaVersion":"latest","sourceType":"module","ecmaFeatures":{"jsx":true}},"rules":{"react/prop-types":0},"overrides":[{"files":["test/**"],"extends":["plugin:jest/recommended","plugin:testing-library/react","plugin:jest/style"],"rules":{"jest/expect-expect":["warn",{"assertFunctionNames":["expect","screen.findByText","screen.getByText"]}]}}]},"size-limit":[{"name":"useIbiza","path":"./src/index.js","import":"{ useIbiza }","limit":"1 s"},{"name":"store","path":"./src/index.js","import":"{ store }","limit":"1 s"},{"name":"createModel","path":"./src/index.js","import":"{ createModel }","limit":"1 s"},{"name":"rawStateOf","path":"./src/index.js","import":"{ rawStateOf }","limit":"1 s"},{"name":"freeze","path":"./src/index.js","import":"{ freeze }","limit":"1 s"}],"prettier":{"trailingComma":"none","printWidth":100,"semi":false,"singleQuote":true,"arrowParens":"avoid"},"peerDependencies":{"react":">=17"},"devDependencies":{"@size-limit/preset-big-lib":"^7.0.1","@swc/core":"^1.2.144","@swc/jest":"^0.2.17","@testing-library/jest-dom":"^5.15.0","@testing-library/react":"^13.0.0","cross-fetch":"^3.1.4","eslint":"^8.18.0","eslint-config-prettier":"^8.5.0","eslint-plugin-jest":"^26.5.3","eslint-plugin-prettier":"^4.0.0","eslint-plugin-react":"^7.30.0","eslint-plugin-react-hooks":"^4.6.0","eslint-plugin-testing-library":"^5.5.1","fetch-mock-jest":"^1.5.1","ibiza":"link:./ibiza","jest":"^28.1.0","jest-environment-jsdom":"^28.1.0","microbundle":"^0.15.0","msw":"^0.42","prettier":"^2.7.1","react":"^18.2.0","react-dom":"^18.2.0","react-error-boundary":"^3.1.4","rimraf":"^3.0.2","size-limit":"^7.0.0"},"dependencies":{"fast-equals":"^4.0.0","micro-memoize":"^4.0.9","use-sync-external-store":"^1.2.0"},"scripts":{"clean":"rimraf dist","test":"jest","build":"microbundle --jsx React.createElement","dev":"microbundle watch --jsx React.createElement --compress false","size":"microbundle && size-limit","lint":"eslint src test --ext .jsx --ext .js"},"readme":"# Ibiza - React State Management for Party Animals\n\nIbiza gets out of your way and simply lets you read and write state as you would with regular\nJavascript assignment. It maintains a global state object and is smart enough to know when to\nrerender your components based on state usage and modification.\n\n## `useIbiza()` ✨\n\nA component calls the `useIbiza` React hook, which returns the store state as a JS Proxy object.\nThis Proxy records when a state property is accessed or \"used\". Then when that property is mutated,\nthe component is rerendered.\n\nThis means that you can mutate your state in any way, but your component will only rerender if you\nmutate state that you have used.\n\nThe following component will rerender when the button is clicked, because `name` has changed.\n\n```jsx\nimport { useIbiza } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n      <button onClick={() => void (state.name = 'Joel')}></button>\n    </div>\n  )\n}\n```\n\nThe following component will not rerender when the button is clicked, because even though `age` has\nbeen mutated, it is not actually being used within the component.\n\n```jsx\nimport { useIbiza } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n      <button onClick={() => void (state.age = 44)}></button>\n    </div>\n  )\n}\n```\n\nState can be mutated from anywhere - not just from within a component:\n\n```js\nimport { useIbiza, store } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n    </div>\n  )\n}\n\n// <App> component will re-render when this line executes, as `name` has changed.\nstore.state.name = 'Ash'\n```\n\n### Initial State\n\nYou can pass some initial state to `useIbiza` which will be merged with existing state in the Ibiza\nstore.\n\n```jsx\nconst App = () => {\n  const state = useIbiza({ user: { name: 'Joel' } })\n\n  return <h1>Hello {state.user.name}</h1>\n}\n```\n\nThis is safe to include in the body of your component, as it will only be merged into the store on\nfirst render.\n\n### Slicing\n\nIbiza supports deeply nested objects, allowing you to design the shape of your state any way you\nlike. To help you work with such nested state, the `useIbiza` hook supports slicing.\n\nThe following example assumes you have an existing state object:\n\n```javascript\n{\n  user: {\n    name: 'Joel',\n    partner: {\n      name: 'Sam',\n    }\n  }\n}\n```\n\nPass a string to `useIbiza` to fetch a specific slice of state. The string should be the path to the\nobject that you want.\n\n```jsx\nconst App = () => {\n  const partner = useIbiza('user.partner')\n\n  return (\n    <div>\n      <h1>Hello {partner.name}</h1>\n      <button onClick={() => void (partner.name = 'Bob')}></button>\n    </div>\n  )\n}\n```\n\nNote that slicing is really only supported as a convenience, and will not generally help with\nperformance.\n\n## `createModel()`\n\nIbiza is at its most powerful when working with models. They provide reusability and flexibility.\n\nCreate a model using the `createModel` helper, where the first argument is the model name, and the\nsecond argument is the initial model state as a plain object.\n\n```javascript\n// model.js\n\nexport default createModel('user', {\n  firstName: 'Joel',\n  lastName: 'Moss',\n  children: [{ firstName: 'Ash' }, { firstName: 'Elijah' }, { firstName: 'Eve' }]\n})\n```\n\n`createModel` returns a hook which you can use. You can now import your model anywhere:\n\n```jsx\n// app.jsx\n\nimport useModel from './model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <div>\n      <h1>Hello {user.firstName}</h1>\n      <ul>\n        {user.children.map((child, i) => (\n          <li key={i}>{child.firstName}</li>\n        ))}\n      </ul>\n    </div>\n  )\n}\n```\n\n### Initial State\n\nSometimes you want to be able to define your model with some initial state that could be provided\ndynamically. For example, from component props or some other parameters.\n\n`createModel` can accept a function as its second argument. This function will be called on\ninitialisation with two arguments; the current `state` and any `props` passed to it when its hook is\nfirst called.\n\n```javascript\n// model.js\n\nexport default createModel('user', (state, props) => ({\n  firstName: 'Joel',\n  lastName: 'Moss'\n  ...props\n}))\n```\n\n```jsx\n// app.jsx\n\nimport useModel from './model'\n\nconst App = ({ yearOfBirth }) => {\n  const user = useModel({ yearOfBirth })\n\n  return (\n    <div>\n      <h1>\n        Hello {user.firstName}, you were born in {user.yearOfBirth}.\n      </h1>\n    </div>\n  )\n}\n```\n\n### Functions\n\nYou can use regular function in your model. They accept the current state as the first argument, and\n`this` will also be the current state (as long as you don't use hash rocket functions).\n\n```jsx\nconst App = () => {\n  const state = useIbiza({\n    count: 0,\n    increment: state => {\n      ++state.count\n    },\n    decrement() {\n      ++this.count\n    }\n  })\n\n  return (\n    <>\n      <h1>Count = {state.count}</h1>\n      <button onClick={state.increment}>Increment</button>\n      <button onClick={state.decrement}>Decrement</button>\n    </>\n  )\n}\n```\n\nWhen reading/writing state within a function, `this` responds to the state at the level where the\nfunction sits. This means that if the function is deeply nested, `this` will not include state lower\ndown.\n\nTo solve this, you can call `this.$model` to access your model, or `this.$root` to access the root\nof the store state.\n\n```javascript\nuseIbiza({\n  deepstate: {\n    user: {\n      name: 'Joel',\n      partner: {\n        name: 'Sam',\n\n        get partner() {\n          // `this` refers to 'deepstate.user.partner'.\n          // `this.$model` refers to 'deepstate.user'.\n          // `this.$root` is the whole store state.\n          return this.$model.name\n        }\n      }\n    }\n  }\n})\n```\n\nFunctions accept any number of arguments just like regular functions do, but don't forget that the\nfirst argument is always the state.\n\n```jsx\nconst App = () => {\n  const user = useIbiza({\n    children: [],\n    addChild(state, firstName, lastName) {\n      state.children.push({ firstName, lastName }) // or `this.children.push(...)`\n    }\n  })\n\n  return (\n    <>\n      <ul>\n        {user.children.map((child, i) => (\n          <li key={i}>\n            {child.firstName} {child.lastName}\n          </li>\n        ))}\n      </ul>\n      <button onClick={() => user.addChild('Ash', 'Moss')}></button>\n    </>\n  )\n}\n```\n\nNote that used state is not tracked within functions. This avoids unnecessary component re-rendering\nwhen state changes that is used by a function. The function will always use the latest state anyway,\nso no need to track the state that it uses.\n\nThis does however, mean that you should not call functions during rendering - use a getter instead.\n\n### Getters and Setters\n\nIbiza supports Javascript getters and setters in your state and models.\n\n```javascript\nexport default createModel('user', {\n  firstName: 'Joel',\n  lastName: 'Moss',\n\n  get fullName() {\n    // You can read/write to your state via `this`.\n    return `${this.firstName} ${this.lastName}`\n  },\n\n  set fullName(value) {\n    const [firstName, lastName] = value.split(' ')\n\n    this.firstName = firstName\n    this.lastName = lastName\n  }\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <h1>Hello {user.fullName}</h1>\n      <button onClick={() => void (user.fullName = 'Bob Bones')}></button>\n    </>\n  )\n}\n```\n\n### Async Functions\n\nFunctions can be async and/or return Promises, and support React's Suspense by default.\n\n```javascript\nexport default createModel('user', {\n  name: 'Joel',\n\n  async doSomething() {\n    return await someAsyncAction()\n  }\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <h1>Hello {user.fullName}</h1>\n      <button onClick={user.doSomething}></button>\n    </>\n  )\n}\n```\n\n### URL Models\n\nBecause reading and writing to/from the server is so common, Ibiza has support to make this easy\nwith URL Models, similar to react-query. Simply use a valid and relative URL as your model name or\nslice.\n\nThe following will fetch the user from the server at `/user`, suspending the component while it does\nso. The data is fetched only when it does not exist in the store.\n\n```jsx\nconst App = () => {\n  const user = useIbiza('/user')\n\n  return <h1>Hello {user.name}</h1>\n}\n```\n\nYou can safely mutate your model, as all mutations will remain local.\n\nYou can write your model state back to the server. It the server responds with JSON, the model will\nbe updated with that response.\n\n```jsx\nconst App = () => {\n  const user = useIbiza('/user')\n\n  const renameUser = async () => {\n    await user.save({ body: { name: 'Bob' } })\n  }\n\n  return (\n    <>\n      <h1>Hello {user.name}</h1>\n      <button onClick={renameUser}></button>\n    </>\n  )\n}\n```\n\nURL Models can also be defined with `createModel`, and accept the same arguments:\n\n```javascript\nexport default createModel('/user')\n```\n\n`createModel` returns a hook which you can use. You can now import your model anywhere:\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return <h1>Hello {user.firstName}</h1>\n}\n```\n\nAdditionally, URL models accept a `fetcher` option, which when provided, will be used as the fetch\nfunction for the model:\n\n```javascript\nexport default createModel('/user', {}, { fetcher: myFetchFunction })\n```\n\n## `createContextModel()`\n\nWrap your component in the `IbizaProvider` higher order component, and instead of `createModel()`,\ncreate your model with `createContextModel()` function. The model will automatically be given a\nunique name specific to the wrapped components in IbizaProvider. Just pass the model definition as\nthe first argument. It accepts the same options as `createModel()` for the second argument.\n\n```jsx\nconst useModel = createContextModel(() => ({\n  // Your model definition...\n  name: 'Awesome!'\n}))\n\nconst App = () => {\n  return (\n    <IbizaProvider>\n      <MyComponent />\n    </IbizaProvider>\n  );\n};\n\nconst MyComponent = () => {\n  const model = useModel()\n\n  return <h1>My model is {model.name}</h1>\n};\n```\n\nEach instance of IbizaProvider will use its own state.\n\n```jsx\nconst useFirstModel = createContextModel(() => ({\n  name: 'FIRST!'\n}))\n\nconst useSecondModel = createContextModel(() => ({\n  name: 'SECOND!'\n}))\n\nconst App = () => {\n  return (\n    <>\n      <IbizaProvider>\n        <MyFirstComponent />\n      </IbizaProvider>\n      <IbizaProvider>\n        <MySecondComponent />\n      </IbizaProvider>\n    </>\n  );\n};\n\nconst MyFirstComponent = () => {\n  const model = useFirstModel();\n\n  return <h1>My model is {model.name}</h1>; // My model is FIRST!\n};\n\nconst MySecondComponent = () => {\n  const model = useSecondModel()\n\n  return <h1>My model is {model.name}</h1> // My model is SECOND!\n};\n```\n\n","readmeFilename":"README.md","_id":"ibiza@2.0.0-alpha.6","_integrity":"sha512-LBDX6yyxHjTay7pXdNipaNtVAKtCz/N6iKmSfNoRniM39OpqUbRwnIJKASF2JsJon4d8DZJMcScmbEdpBqAXWA==","_resolved":"/private/var/folders/3b/b6pthvr51cg1755k2jxx8www0000gn/T/def338708eccf9993818bc58d658fa72/ibiza-2.0.0-alpha.6.tgz","_from":"file:ibiza-2.0.0-alpha.6.tgz","_nodeVersion":"18.4.0","_npmVersion":"8.12.1","dist":{"integrity":"sha512-LBDX6yyxHjTay7pXdNipaNtVAKtCz/N6iKmSfNoRniM39OpqUbRwnIJKASF2JsJon4d8DZJMcScmbEdpBqAXWA==","shasum":"e452511810a8321774fb822c20366dd09f4edc39","tarball":"https://registry.npmjs.org/ibiza/-/ibiza-2.0.0-alpha.6.tgz","fileCount":10,"unpackedSize":319453,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCID2mmez6RfRgECvAD5Alfy8FMbFEcTl4vbpnzdFiEt1OAiBzitzcG4XTEhGtg/lLp0mUbw3lMzIutdIFyDJgHN7Osw=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJivCE4ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmocfg//ZnugvhL0mqjU9SvGjvbUh7Q9rK3u85dE6x77GTRSUqJa5rZO\r\n49eozbYiq/cucC02o7wa4oH4EQKhzJld1tdqXo5cECAVUt5WD7vICXfdutsr\r\nXLyMCr99YkYha+BXLBOvM6DbVRY4vLZbNJFxIyv8TooRr4IPPk1x8kP2XkAG\r\nvmoUmOw8hD7m8c/jFgF1oRQNHkLZaL6e2u5VIwZvBfw6x2URfhnMxt1TGSUS\r\nTJdxCEJ/LvnJG/KuvSveqxvHM8bQrRV4JN2gt1XRNx5/xwHBT3kqXAsxiJ68\r\nT+HroVq3dSFBt4V2fxSQ0R26GVrNxmbEZJNJ7wHR7Vw+Mw/FzpXpJs3lC5cx\r\nmaXieI0NmzrJfFYgy4EbRq+VBIS9oxbLGistUYeMWRzTPYt9E3v0lZkRj/82\r\nmgXa7BhkFKCHacpoDkOF9pZTwOkLPMcFydL83Lkz+D5QJZqFIg0pmXL7iD+T\r\nx3exOD0hdD/rK+5ipQKrgCK2hPLfCCsyYr1ZfPcUw3Qd4jLQdG2wkoi+UFkF\r\n5X/KCfNcqleGS7WL2D+E0YDi33Pl4QaGbaQKdjKBuDQvntEwZV/UPaTwtSK2\r\n/zJTPBb91t77t3iKM9+niCS8mn724IajBSPFtqpgezH3DV+bk0G150Hs6Bl5\r\n+f+MtmVyO5qKoJzi9iPFPK91v+S0fZ6NH20=\r\n=6ll/\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"joelmoss","email":"joel@developwithstyle.com"},"directories":{},"maintainers":[{"name":"joelmoss","email":"joel@developwithstyle.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ibiza_2.0.0-alpha.6_1656496440124_0.9748939053647099"},"_hasShrinkwrap":false},"2.0.0-alpha.7":{"name":"ibiza","author":{"name":"Joel Moss"},"version":"2.0.0-alpha.7","description":"React State Management for Party Animals","license":"MIT","homepage":"https://github.com/joelmoss/ibiza","repository":{"type":"git","url":"git+https://github.com/joelmoss/ibiza.git"},"bugs":{"url":"https://github.com/joelmoss/ibiza/issues"},"keywords":["react","state","proxy"],"type":"module","source":"src/index.js","main":"dist/ibiza.cjs","module":"dist/ibiza.module.js","unpkg":"dist/ibiza.umd.js","exports":{"require":"./dist/ibiza.cjs","default":"./dist/ibiza.modern.js"},"sideEffects":false,"eslintConfig":{"extends":["eslint:recommended","plugin:react/recommended","plugin:react-hooks/recommended","plugin:prettier/recommended"],"settings":{"react":{"version":"detect"}},"env":{"browser":true,"node":false,"es6":true},"parserOptions":{"ecmaVersion":"latest","sourceType":"module","ecmaFeatures":{"jsx":true}},"rules":{"react/prop-types":0},"overrides":[{"files":["test/**"],"extends":["plugin:jest/recommended","plugin:testing-library/react","plugin:jest/style"],"rules":{"jest/expect-expect":["warn",{"assertFunctionNames":["expect","screen.findByText","screen.getByText"]}]}}]},"size-limit":[{"name":"useIbiza","path":"./src/index.js","import":"{ useIbiza }","limit":"1 s"},{"name":"store","path":"./src/index.js","import":"{ store }","limit":"1 s"},{"name":"createModel","path":"./src/index.js","import":"{ createModel }","limit":"1 s"},{"name":"rawStateOf","path":"./src/index.js","import":"{ rawStateOf }","limit":"1 s"},{"name":"freeze","path":"./src/index.js","import":"{ freeze }","limit":"1 s"}],"prettier":{"trailingComma":"none","printWidth":100,"semi":false,"singleQuote":true,"arrowParens":"avoid"},"peerDependencies":{"react":">=17"},"devDependencies":{"@size-limit/preset-big-lib":"^7.0.1","@swc/core":"^1.2.144","@swc/jest":"^0.2.17","@testing-library/dom":"^8.14.0","@testing-library/jest-dom":"^5.15.0","@testing-library/react":"^13.0.0","@testing-library/user-event":"^14.2.1","cross-fetch":"^3.1.4","eslint":"^8.18.0","eslint-config-prettier":"^8.5.0","eslint-plugin-jest":"^26.5.3","eslint-plugin-prettier":"^4.0.0","eslint-plugin-react":"^7.30.0","eslint-plugin-react-hooks":"^4.6.0","eslint-plugin-testing-library":"^5.5.1","fetch-mock-jest":"^1.5.1","ibiza":"link:./ibiza","jest":"^28.1.0","jest-environment-jsdom":"^28.1.0","microbundle":"^0.15.0","msw":"^0.42","prettier":"^2.7.1","react":"^18.2.0","react-dom":"^18.2.0","react-error-boundary":"^3.1.4","rimraf":"^3.0.2","size-limit":"^7.0.0"},"dependencies":{"fast-equals":"^4.0.0","micro-memoize":"^4.0.9","use-sync-external-store":"^1.2.0"},"scripts":{"clean":"rimraf dist","test":"jest","build":"microbundle --jsx React.createElement","dev":"microbundle watch --jsx React.createElement --compress false","size":"microbundle && size-limit","lint":"eslint src test --ext .jsx --ext .js"},"readme":"# Ibiza - React State Management for Party Animals\n\nIbiza gets out of your way and simply lets you read and write state as you would with regular\nJavascript assignment. It maintains a global state object and is smart enough to know when to\nrerender your components based on state usage and modification.\n\n## `useIbiza()` ✨\n\nA component calls the `useIbiza` React hook, which returns the store state as a JS Proxy object.\nThis Proxy records when a state property is accessed or \"used\". Then when that property is mutated,\nthe component is rerendered.\n\nThis means that you can mutate your state in any way, but your component will only rerender if you\nmutate state that you have used.\n\nThe following component will rerender when the button is clicked, because `name` has changed.\n\n```jsx\nimport { useIbiza } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n      <button onClick={() => void (state.name = 'Joel')}></button>\n    </div>\n  )\n}\n```\n\nThe following component will not rerender when the button is clicked, because even though `age` has\nbeen mutated, it is not actually being used within the component.\n\n```jsx\nimport { useIbiza } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n      <button onClick={() => void (state.age = 44)}></button>\n    </div>\n  )\n}\n```\n\nState can be mutated from anywhere - not just from within a component:\n\n```js\nimport { useIbiza, store } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n    </div>\n  )\n}\n\n// <App> component will re-render when this line executes, as `name` has changed.\nstore.state.name = 'Ash'\n```\n\n### Initial State\n\nYou can pass some initial state to `useIbiza` which will be merged with existing state in the Ibiza\nstore.\n\n```jsx\nconst App = () => {\n  const state = useIbiza({ user: { name: 'Joel' } })\n\n  return <h1>Hello {state.user.name}</h1>\n}\n```\n\nThis is safe to include in the body of your component, as it will only be merged into the store on\nfirst render.\n\n### Slicing\n\nIbiza supports deeply nested objects, allowing you to design the shape of your state any way you\nlike. To help you work with such nested state, the `useIbiza` hook supports slicing.\n\nThe following example assumes you have an existing state object:\n\n```javascript\n{\n  user: {\n    name: 'Joel',\n    partner: {\n      name: 'Sam',\n    }\n  }\n}\n```\n\nPass a string to `useIbiza` to fetch a specific slice of state. The string should be the path to the\nobject that you want.\n\n```jsx\nconst App = () => {\n  const partner = useIbiza('user.partner')\n\n  return (\n    <div>\n      <h1>Hello {partner.name}</h1>\n      <button onClick={() => void (partner.name = 'Bob')}></button>\n    </div>\n  )\n}\n```\n\nNote that slicing is really only supported as a convenience, and will not generally help with\nperformance.\n\n## `createModel()`\n\nIbiza is at its most powerful when working with models. They provide reusability and flexibility.\n\nCreate a model using the `createModel` helper, where the first argument is the model name, and the\nsecond argument is the initial model state as a plain object.\n\n```javascript\n// model.js\n\nexport default createModel('user', {\n  firstName: 'Joel',\n  lastName: 'Moss',\n  children: [{ firstName: 'Ash' }, { firstName: 'Elijah' }, { firstName: 'Eve' }]\n})\n```\n\n`createModel` returns a hook which you can use. You can now import your model anywhere:\n\n```jsx\n// app.jsx\n\nimport useModel from './model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <div>\n      <h1>Hello {user.firstName}</h1>\n      <ul>\n        {user.children.map((child, i) => (\n          <li key={i}>{child.firstName}</li>\n        ))}\n      </ul>\n    </div>\n  )\n}\n```\n\n### Initial State\n\nSometimes you want to be able to define your model with some initial state that could be provided\ndynamically. For example, from component props or some other parameters.\n\n`createModel` can accept a function as its second argument. This function will be called on\ninitialisation with two arguments; the current `state` and any `props` passed to it when its hook is\nfirst called.\n\n```javascript\n// model.js\n\nexport default createModel('user', (state, props) => ({\n  firstName: 'Joel',\n  lastName: 'Moss'\n  ...props\n}))\n```\n\n```jsx\n// app.jsx\n\nimport useModel from './model'\n\nconst App = ({ yearOfBirth }) => {\n  const user = useModel({ yearOfBirth })\n\n  return (\n    <div>\n      <h1>\n        Hello {user.firstName}, you were born in {user.yearOfBirth}.\n      </h1>\n    </div>\n  )\n}\n```\n\n### Functions\n\nYou can use regular function in your model. They accept the current state as the first argument, and\n`this` will also be the current state (as long as you don't use hash rocket functions).\n\n```jsx\nconst App = () => {\n  const state = useIbiza({\n    count: 0,\n    increment: state => {\n      ++state.count\n    },\n    decrement() {\n      ++this.count\n    }\n  })\n\n  return (\n    <>\n      <h1>Count = {state.count}</h1>\n      <button onClick={state.increment}>Increment</button>\n      <button onClick={state.decrement}>Decrement</button>\n    </>\n  )\n}\n```\n\nWhen reading/writing state within a function, `this` responds to the state at the level where the\nfunction sits. This means that if the function is deeply nested, `this` will not include state lower\ndown.\n\nTo solve this, you can call `this.$model` to access your model, or `this.$root` to access the root\nof the store state.\n\n```javascript\nuseIbiza({\n  deepstate: {\n    user: {\n      name: 'Joel',\n      partner: {\n        name: 'Sam',\n\n        get partner() {\n          // `this` refers to 'deepstate.user.partner'.\n          // `this.$model` refers to 'deepstate.user'.\n          // `this.$root` is the whole store state.\n          return this.$model.name\n        }\n      }\n    }\n  }\n})\n```\n\nFunctions accept any number of arguments just like regular functions do, but don't forget that the\nfirst argument is always the state.\n\n```jsx\nconst App = () => {\n  const user = useIbiza({\n    children: [],\n    addChild(state, firstName, lastName) {\n      state.children.push({ firstName, lastName }) // or `this.children.push(...)`\n    }\n  })\n\n  return (\n    <>\n      <ul>\n        {user.children.map((child, i) => (\n          <li key={i}>\n            {child.firstName} {child.lastName}\n          </li>\n        ))}\n      </ul>\n      <button onClick={() => user.addChild('Ash', 'Moss')}></button>\n    </>\n  )\n}\n```\n\nNote that used state is not tracked within functions. This avoids unnecessary component re-rendering\nwhen state changes that is used by a function. The function will always use the latest state anyway,\nso no need to track the state that it uses.\n\nThis does however, mean that you should not call functions during rendering - use a getter instead.\n\n### Getters and Setters\n\nIbiza supports Javascript getters and setters in your state and models.\n\n```javascript\nexport default createModel('user', {\n  firstName: 'Joel',\n  lastName: 'Moss',\n\n  get fullName() {\n    // You can read/write to your state via `this`.\n    return `${this.firstName} ${this.lastName}`\n  },\n\n  set fullName(value) {\n    const [firstName, lastName] = value.split(' ')\n\n    this.firstName = firstName\n    this.lastName = lastName\n  }\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <h1>Hello {user.fullName}</h1>\n      <button onClick={() => void (user.fullName = 'Bob Bones')}></button>\n    </>\n  )\n}\n```\n\n### Async Functions\n\nFunctions can be async and/or return Promises, and support React's Suspense by default.\n\n```javascript\nexport default createModel('user', {\n  name: 'Joel',\n\n  async doSomething() {\n    return await someAsyncAction()\n  }\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <h1>Hello {user.fullName}</h1>\n      <button onClick={user.doSomething}></button>\n    </>\n  )\n}\n```\n\n### URL Models\n\nBecause reading and writing to/from the server is so common, Ibiza has support to make this easy\nwith URL Models, similar to react-query. Simply use a valid and relative URL as your model name or\nslice.\n\nThe following will fetch the user from the server at `/user`, suspending the component while it does\nso. The data is fetched only when it does not exist in the store.\n\n```jsx\nconst App = () => {\n  const user = useIbiza('/user')\n\n  return <h1>Hello {user.name}</h1>\n}\n```\n\nYou can safely mutate your model, as all mutations will remain local.\n\nYou can write your model state back to the server. It the server responds with JSON, the model will\nbe updated with that response.\n\n```jsx\nconst App = () => {\n  const user = useIbiza('/user')\n\n  const renameUser = async () => {\n    await user.save({ body: { name: 'Bob' } })\n  }\n\n  return (\n    <>\n      <h1>Hello {user.name}</h1>\n      <button onClick={renameUser}></button>\n    </>\n  )\n}\n```\n\nURL Models can also be defined with `createModel`, and accept the same arguments:\n\n```javascript\nexport default createModel('/user')\n```\n\n`createModel` returns a hook which you can use. You can now import your model anywhere:\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return <h1>Hello {user.firstName}</h1>\n}\n```\n\nAdditionally, URL models accept a `fetcher` option, which when provided, will be used as the fetch\nfunction for the model:\n\n```javascript\nexport default createModel('/user', {}, { fetcher: myFetchFunction })\n```\n\n## `createContextModel()`\n\nWrap your component in the `IbizaProvider` higher order component, and instead of `createModel()`,\ncreate your model with `createContextModel()` function. The model will automatically be given a\nunique name specific to the wrapped components in IbizaProvider. Just pass the model definition as\nthe first argument. It accepts the same options as `createModel()` for the second argument.\n\n```jsx\nconst useModel = createContextModel(() => ({\n  // Your model definition...\n  name: 'Awesome!'\n}))\n\nconst App = () => {\n  return (\n    <IbizaProvider>\n      <MyComponent />\n    </IbizaProvider>\n  );\n};\n\nconst MyComponent = () => {\n  const model = useModel()\n\n  return <h1>My model is {model.name}</h1>\n};\n```\n\nEach instance of IbizaProvider will use its own state.\n\n```jsx\nconst useFirstModel = createContextModel(() => ({\n  name: 'FIRST!'\n}))\n\nconst useSecondModel = createContextModel(() => ({\n  name: 'SECOND!'\n}))\n\nconst App = () => {\n  return (\n    <>\n      <IbizaProvider>\n        <MyFirstComponent />\n      </IbizaProvider>\n      <IbizaProvider>\n        <MySecondComponent />\n      </IbizaProvider>\n    </>\n  );\n};\n\nconst MyFirstComponent = () => {\n  const model = useFirstModel();\n\n  return <h1>My model is {model.name}</h1>; // My model is FIRST!\n};\n\nconst MySecondComponent = () => {\n  const model = useSecondModel()\n\n  return <h1>My model is {model.name}</h1> // My model is SECOND!\n};\n```\n\n","readmeFilename":"README.md","_id":"ibiza@2.0.0-alpha.7","_integrity":"sha512-SSpC8wJW+n9mK9b/iizJ9eZ9z91jsTR+5fqI+bUPCSWTmJK8G7qzgpfDEGGijEiuNXtjmECDD5PPsWmk8fHh2w==","_resolved":"/private/var/folders/3b/b6pthvr51cg1755k2jxx8www0000gn/T/4f7fdd17dd2485d2b7321e748fdb532d/ibiza-2.0.0-alpha.7.tgz","_from":"file:ibiza-2.0.0-alpha.7.tgz","_nodeVersion":"18.4.0","_npmVersion":"8.12.1","dist":{"integrity":"sha512-SSpC8wJW+n9mK9b/iizJ9eZ9z91jsTR+5fqI+bUPCSWTmJK8G7qzgpfDEGGijEiuNXtjmECDD5PPsWmk8fHh2w==","shasum":"ca42c6615ebeea503ded6a0cfd0fcea212452e71","tarball":"https://registry.npmjs.org/ibiza/-/ibiza-2.0.0-alpha.7.tgz","fileCount":10,"unpackedSize":317045,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCV8RD6jjELJEH89DZ2VrLZmzA6xL7QieXC/WqRxn0FDAIgLU3/DTwQYPywZNPqdT0yVo6FRV5b0EaIOGapamNK9/U="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJivIETACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpRfg//UwUzuQL3Cz0yRahfMTxvxIHvhglksVZoLbQohtZLOwMfrmo1\r\n5xuushNXnJ9humHutYFeN62g8SNFnreISZZb63JKUGs0GaYeaXdUKe2B1esO\r\n1a9sU28xDtv4A2C0UHPsxX5hUTDYzPqgjUsTTgCvkq8NpofIjSHZ72P1X9CY\r\nUE8DJfQNtEIRlfiOgCKK//R6zesc1FU/1HGQAe0JqxsRRz7bqUuB8Y0ES6nL\r\ntH+B+0kiWL2g3XfdvM9KW4AZ2vl3fwFq8rM3ZoepO0+B6DEF7Ra58qyIrC4t\r\nCZ6itmyVZuM+2dfnNhrxWXsUUl5bZD0QnEJp2koHlullu0NiJg/LnKGowhfB\r\n/YAG5HJ88licyerBptrf6udRujjAR7dzpSuF95nQG8wTgPRsUkWDAvjchTfC\r\nWETXC4vQ0JblDmIqekhg+g3mAB5+Z8umcroQYb/D2xkPZHut/Ryor0aiHU43\r\nFR1odj4RY5P9z7Mlq0QDTQ0NIqfNCBRAlnuMQEQTDp/vg1sum+gnujIDeTgJ\r\nSBwoPuFkRFvXJALFIbC9t0JJrvq8BxuMscC8mIT6musLpotnYmBnkP2AUBnq\r\nXKqBER4s2k0xhTq39P8zemx3CFBvN//VfcCRfTEKqQYzuKzYWEBRNb5oB7V4\r\nhm+nd/z/pki+3sPHsOMSw92KQGqdq3OZmCc=\r\n=pcE+\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"joelmoss","email":"joel@developwithstyle.com"},"directories":{},"maintainers":[{"name":"joelmoss","email":"joel@developwithstyle.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ibiza_2.0.0-alpha.7_1656520978523_0.7675088608937952"},"_hasShrinkwrap":false},"2.0.0-alpha.8":{"name":"ibiza","author":{"name":"Joel Moss"},"version":"2.0.0-alpha.8","description":"React State Management for Party Animals","license":"MIT","homepage":"https://github.com/joelmoss/ibiza","repository":{"type":"git","url":"git+https://github.com/joelmoss/ibiza.git"},"bugs":{"url":"https://github.com/joelmoss/ibiza/issues"},"keywords":["react","state","proxy"],"type":"module","source":"src/index.js","main":"dist/ibiza.cjs","module":"dist/ibiza.module.js","unpkg":"dist/ibiza.umd.js","exports":{"require":"./dist/ibiza.cjs","default":"./dist/ibiza.modern.js"},"sideEffects":false,"eslintConfig":{"extends":["eslint:recommended","plugin:react/recommended","plugin:react-hooks/recommended","plugin:prettier/recommended"],"settings":{"react":{"version":"detect"}},"env":{"browser":true,"node":false,"es6":true},"parserOptions":{"ecmaVersion":"latest","sourceType":"module","ecmaFeatures":{"jsx":true}},"rules":{"react/prop-types":0},"overrides":[{"files":["test/**"],"extends":["plugin:jest/recommended","plugin:testing-library/react","plugin:jest/style"],"rules":{"jest/expect-expect":["warn",{"assertFunctionNames":["expect","screen.findByText","screen.getByText"]}]}}]},"size-limit":[{"name":"useIbiza","path":"./src/index.js","import":"{ useIbiza }","limit":"1 s"},{"name":"store","path":"./src/index.js","import":"{ store }","limit":"1 s"},{"name":"createModel","path":"./src/index.js","import":"{ createModel }","limit":"1 s"},{"name":"rawStateOf","path":"./src/index.js","import":"{ rawStateOf }","limit":"1 s"},{"name":"freeze","path":"./src/index.js","import":"{ freeze }","limit":"1 s"}],"prettier":{"trailingComma":"none","printWidth":100,"semi":false,"singleQuote":true,"arrowParens":"avoid"},"peerDependencies":{"react":">=17"},"devDependencies":{"@size-limit/preset-big-lib":"^7.0.1","@swc/core":"^1.2.144","@swc/jest":"^0.2.17","@testing-library/dom":"^8.14.0","@testing-library/jest-dom":"^5.15.0","@testing-library/react":"^13.0.0","@testing-library/user-event":"^14.2.1","cross-fetch":"^3.1.4","eslint":"^8.18.0","eslint-config-prettier":"^8.5.0","eslint-plugin-jest":"^26.5.3","eslint-plugin-prettier":"^4.0.0","eslint-plugin-react":"^7.30.0","eslint-plugin-react-hooks":"^4.6.0","eslint-plugin-testing-library":"^5.5.1","fetch-mock-jest":"^1.5.1","ibiza":"link:./ibiza","jest":"^28.1.0","jest-environment-jsdom":"^28.1.0","microbundle":"^0.15.0","msw":"^0.42","prettier":"^2.7.1","react":"^18.2.0","react-dom":"^18.2.0","react-error-boundary":"^3.1.4","rimraf":"^3.0.2","size-limit":"^7.0.0"},"dependencies":{"fast-equals":"^4.0.0","micro-memoize":"^4.0.9","use-sync-external-store":"^1.2.0"},"scripts":{"clean":"rimraf dist","test":"jest","build":"microbundle --jsx React.createElement","dev":"microbundle watch --jsx React.createElement --compress false","size":"microbundle && size-limit","lint":"eslint src test --ext .jsx --ext .js"},"readme":"# Ibiza - React State Management for Party Animals\n\nIbiza gets out of your way and simply lets you read and write state as you would with regular\nJavascript assignment. It maintains a global state object and is smart enough to know when to\nrerender your components based on state usage and modification.\n\n## `useIbiza()` ✨\n\nA component calls the `useIbiza` React hook, which returns the store state as a JS Proxy object.\nThis Proxy records when a state property is accessed or \"used\". Then when that property is mutated,\nthe component is rerendered.\n\nThis means that you can mutate your state in any way, but your component will only rerender if you\nmutate state that you have used.\n\nThe following component will rerender when the button is clicked, because `name` has changed.\n\n```jsx\nimport { useIbiza } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n      <button onClick={() => void (state.name = 'Joel')}></button>\n    </div>\n  )\n}\n```\n\nThe following component will not rerender when the button is clicked, because even though `age` has\nbeen mutated, it is not actually being used within the component.\n\n```jsx\nimport { useIbiza } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n      <button onClick={() => void (state.age = 44)}></button>\n    </div>\n  )\n}\n```\n\nState can be mutated from anywhere - not just from within a component:\n\n```js\nimport { useIbiza, store } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n    </div>\n  )\n}\n\n// <App> component will re-render when this line executes, as `name` has changed.\nstore.state.name = 'Ash'\n```\n\n### Initial State\n\nYou can pass some initial state to `useIbiza` which will be merged with existing state in the Ibiza\nstore.\n\n```jsx\nconst App = () => {\n  const state = useIbiza({ user: { name: 'Joel' } })\n\n  return <h1>Hello {state.user.name}</h1>\n}\n```\n\nThis is safe to include in the body of your component, as it will only be merged into the store on\nfirst render.\n\n### Slicing\n\nIbiza supports deeply nested objects, allowing you to design the shape of your state any way you\nlike. To help you work with such nested state, the `useIbiza` hook supports slicing.\n\nThe following example assumes you have an existing state object:\n\n```javascript\n{\n  user: {\n    name: 'Joel',\n    partner: {\n      name: 'Sam',\n    }\n  }\n}\n```\n\nPass a string to `useIbiza` to fetch a specific slice of state. The string should be the path to the\nobject that you want.\n\n```jsx\nconst App = () => {\n  const partner = useIbiza('user.partner')\n\n  return (\n    <div>\n      <h1>Hello {partner.name}</h1>\n      <button onClick={() => void (partner.name = 'Bob')}></button>\n    </div>\n  )\n}\n```\n\nNote that slicing is really only supported as a convenience, and will not generally help with\nperformance.\n\n## `createModel()`\n\nIbiza is at its most powerful when working with models. They provide reusability and flexibility.\n\nCreate a model using the `createModel` helper, where the first argument is the model name, and the\nsecond argument is the initial model state as a plain object.\n\n```javascript\n// model.js\n\nexport default createModel('user', {\n  firstName: 'Joel',\n  lastName: 'Moss',\n  children: [{ firstName: 'Ash' }, { firstName: 'Elijah' }, { firstName: 'Eve' }]\n})\n```\n\n`createModel` returns a hook which you can use. You can now import your model anywhere:\n\n```jsx\n// app.jsx\n\nimport useModel from './model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <div>\n      <h1>Hello {user.firstName}</h1>\n      <ul>\n        {user.children.map((child, i) => (\n          <li key={i}>{child.firstName}</li>\n        ))}\n      </ul>\n    </div>\n  )\n}\n```\n\n### Initial State\n\nSometimes you want to be able to define your model with some initial state that could be provided\ndynamically. For example, from component props or some other parameters.\n\n`createModel` can accept a function as its second argument. This function will be called on\ninitialisation with two arguments; the current `state` and any `props` passed to it when its hook is\nfirst called.\n\n```javascript\n// model.js\n\nexport default createModel('user', (state, props) => ({\n  firstName: 'Joel',\n  lastName: 'Moss'\n  ...props\n}))\n```\n\n```jsx\n// app.jsx\n\nimport useModel from './model'\n\nconst App = ({ yearOfBirth }) => {\n  const user = useModel({ yearOfBirth })\n\n  return (\n    <div>\n      <h1>\n        Hello {user.firstName}, you were born in {user.yearOfBirth}.\n      </h1>\n    </div>\n  )\n}\n```\n\n### Functions\n\nYou can use regular function in your model. They accept the current state as the first argument, and\n`this` will also be the current state (as long as you don't use hash rocket functions).\n\n```jsx\nconst App = () => {\n  const state = useIbiza({\n    count: 0,\n    increment: state => {\n      ++state.count\n    },\n    decrement() {\n      ++this.count\n    }\n  })\n\n  return (\n    <>\n      <h1>Count = {state.count}</h1>\n      <button onClick={state.increment}>Increment</button>\n      <button onClick={state.decrement}>Decrement</button>\n    </>\n  )\n}\n```\n\nWhen reading/writing state within a function, `this` responds to the state at the level where the\nfunction sits. This means that if the function is deeply nested, `this` will not include state lower\ndown.\n\nTo solve this, you can call `this.$model` to access your model, or `this.$root` to access the root\nof the store state.\n\n```javascript\nuseIbiza({\n  deepstate: {\n    user: {\n      name: 'Joel',\n      partner: {\n        name: 'Sam',\n\n        get partner() {\n          // `this` refers to 'deepstate.user.partner'.\n          // `this.$model` refers to 'deepstate.user'.\n          // `this.$root` is the whole store state.\n          return this.$model.name\n        }\n      }\n    }\n  }\n})\n```\n\nFunctions accept any number of arguments just like regular functions do, but don't forget that the\nfirst argument is always the state.\n\n```jsx\nconst App = () => {\n  const user = useIbiza({\n    children: [],\n    addChild(state, firstName, lastName) {\n      state.children.push({ firstName, lastName }) // or `this.children.push(...)`\n    }\n  })\n\n  return (\n    <>\n      <ul>\n        {user.children.map((child, i) => (\n          <li key={i}>\n            {child.firstName} {child.lastName}\n          </li>\n        ))}\n      </ul>\n      <button onClick={() => user.addChild('Ash', 'Moss')}></button>\n    </>\n  )\n}\n```\n\nNote that used state is not tracked within functions. This avoids unnecessary component re-rendering\nwhen state changes that is used by a function. The function will always use the latest state anyway,\nso no need to track the state that it uses.\n\nThis does however, mean that you should not call functions during rendering - use a getter instead.\n\n### Getters and Setters\n\nIbiza supports Javascript getters and setters in your state and models.\n\n```javascript\nexport default createModel('user', {\n  firstName: 'Joel',\n  lastName: 'Moss',\n\n  get fullName() {\n    // You can read/write to your state via `this`.\n    return `${this.firstName} ${this.lastName}`\n  },\n\n  set fullName(value) {\n    const [firstName, lastName] = value.split(' ')\n\n    this.firstName = firstName\n    this.lastName = lastName\n  }\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <h1>Hello {user.fullName}</h1>\n      <button onClick={() => void (user.fullName = 'Bob Bones')}></button>\n    </>\n  )\n}\n```\n\n### Async Functions\n\nFunctions can be async and/or return Promises, and support React's Suspense by default.\n\n```javascript\nexport default createModel('user', {\n  name: 'Joel',\n\n  async doSomething() {\n    return await someAsyncAction()\n  }\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <h1>Hello {user.fullName}</h1>\n      <button onClick={user.doSomething}></button>\n    </>\n  )\n}\n```\n\n### URL Models\n\nBecause reading and writing to/from the server is so common, Ibiza has support to make this easy\nwith URL Models, similar to react-query. Simply use a valid and relative URL as your model name or\nslice.\n\nThe following will fetch the user from the server at `/user`, suspending the component while it does\nso. The data is fetched only when it does not exist in the store.\n\n```jsx\nconst App = () => {\n  const user = useIbiza('/user')\n\n  return <h1>Hello {user.name}</h1>\n}\n```\n\nYou can safely mutate your model, as all mutations will remain local.\n\nYou can write your model state back to the server. It the server responds with JSON, the model will\nbe updated with that response.\n\n```jsx\nconst App = () => {\n  const user = useIbiza('/user')\n\n  const renameUser = async () => {\n    await user.save({ body: { name: 'Bob' } })\n  }\n\n  return (\n    <>\n      <h1>Hello {user.name}</h1>\n      <button onClick={renameUser}></button>\n    </>\n  )\n}\n```\n\nURL Models can also be defined with `createModel`, and accept the same arguments:\n\n```javascript\nexport default createModel('/user')\n```\n\n`createModel` returns a hook which you can use. You can now import your model anywhere:\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return <h1>Hello {user.firstName}</h1>\n}\n```\n\nAdditionally, URL models accept a `fetcher` option, which when provided, will be used as the fetch\nfunction for the model:\n\n```javascript\nexport default createModel('/user', {}, { fetcher: myFetchFunction })\n```\n\n## `createContextModel()`\n\nWrap your component in the `IbizaProvider` higher order component, and instead of `createModel()`,\ncreate your model with `createContextModel()` function. The model will automatically be given a\nunique name specific to the wrapped components in IbizaProvider. Just pass the model definition as\nthe first argument. It accepts the same options as `createModel()` for the second argument.\n\n```jsx\nconst useModel = createContextModel(() => ({\n  // Your model definition...\n  name: 'Awesome!'\n}))\n\nconst App = () => {\n  return (\n    <IbizaProvider>\n      <MyComponent />\n    </IbizaProvider>\n  );\n};\n\nconst MyComponent = () => {\n  const model = useModel()\n\n  return <h1>My model is {model.name}</h1>\n};\n```\n\nEach instance of IbizaProvider will use its own state.\n\n```jsx\nconst useFirstModel = createContextModel(() => ({\n  name: 'FIRST!'\n}))\n\nconst useSecondModel = createContextModel(() => ({\n  name: 'SECOND!'\n}))\n\nconst App = () => {\n  return (\n    <>\n      <IbizaProvider>\n        <MyFirstComponent />\n      </IbizaProvider>\n      <IbizaProvider>\n        <MySecondComponent />\n      </IbizaProvider>\n    </>\n  );\n};\n\nconst MyFirstComponent = () => {\n  const model = useFirstModel();\n\n  return <h1>My model is {model.name}</h1>; // My model is FIRST!\n};\n\nconst MySecondComponent = () => {\n  const model = useSecondModel()\n\n  return <h1>My model is {model.name}</h1> // My model is SECOND!\n};\n```\n\n","readmeFilename":"README.md","_id":"ibiza@2.0.0-alpha.8","_integrity":"sha512-Vr+jaoCRq/vOp7XzFCgsamkXcokxIOP8VS+GyZ5tON6wfGNUO63evG9fGP8JSSeRMKizEJuCw+lV4ctvJKGb0Q==","_resolved":"/private/var/folders/3b/b6pthvr51cg1755k2jxx8www0000gn/T/2381e7d8cedca1694abec4ae09b89b14/ibiza-2.0.0-alpha.8.tgz","_from":"file:ibiza-2.0.0-alpha.8.tgz","_nodeVersion":"18.4.0","_npmVersion":"8.12.1","dist":{"integrity":"sha512-Vr+jaoCRq/vOp7XzFCgsamkXcokxIOP8VS+GyZ5tON6wfGNUO63evG9fGP8JSSeRMKizEJuCw+lV4ctvJKGb0Q==","shasum":"67648a60e5afa6274f0e57e63197da95af6826f6","tarball":"https://registry.npmjs.org/ibiza/-/ibiza-2.0.0-alpha.8.tgz","fileCount":10,"unpackedSize":320001,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCxEyKB93lLI8Rze7Ib3U0zG6KIPRb+RS6M9ozy4ZkLswIhANuYR/tVDAEuygUioakWGmRXbFNBSdKc9x2f/8a3Fz0o"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiwwJuACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmp3RQ/9HFN18PpNTD6+UZ0wEicfHsncdmHEvvKeSaDztPxxyafiHM4x\r\nguU98GT1d+fhqDkxnq8UJZ9F1V2klV3fFrnZrlKJ0/b5ndppLOnyhcH6J1aS\r\nHR8OXIzZ+RzcOHj+jJcNU8dj9SI5O/K6F85BEq5nPLJVCt8YLnF0LwlYtbBt\r\ntnFqJY1jUba0CG4fzOjXCocuB4Wbw8Z8JhCm1Lo62UwijRBzNKOtw3Z0Xny4\r\nVkKoer8Yd+1wwZsk2HYPJ23cCP5ILDIFyk6rxSRIxACu0E/nflpFWAYEhMee\r\nbp/rR1E87Sonke59ra7mFtGR6HmYeUoGTSDppMXcRyjQG7BNi5qaCEiuY65k\r\n37GqTbuAIIz8i8vFlKQFtwmeaj9h+n12xP08+8c3pVH4/p8llq2QA7rs7KFz\r\nSXzMTvT81Eil6KLuoc46aS/mliB/B3+vZqY/eEKwMZJSUHDC5PiLD3VT4Vcy\r\nEOY1Kt7cTMPvXf2663Ootox+dYtuv5JOad/5oSYzMZlOVzQ2Q5z5mO4XC54+\r\nZ6y4/n2o+h7AB8Z4sUPplG/o5ELMW7a7B/9qRSgMxFTs7b9+AlTfqfcggX01\r\n/8dUvH919TErrdZPVtvFZJuui1tMaIIOKe/UYe353cgkhZRr2jmgmfKGscdF\r\nYZ8Jj8fa19pzNCuWwIQl2v3kBq2qPboqMbU=\r\n=xprP\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"joelmoss","email":"joel@developwithstyle.com"},"directories":{},"maintainers":[{"name":"joelmoss","email":"joel@developwithstyle.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ibiza_2.0.0-alpha.8_1656947310264_0.1355821562645585"},"_hasShrinkwrap":false},"2.0.0-alpha.9":{"name":"ibiza","author":{"name":"Joel Moss"},"version":"2.0.0-alpha.9","description":"React State Management for Party Animals","license":"MIT","homepage":"https://github.com/joelmoss/ibiza","repository":{"type":"git","url":"git+https://github.com/joelmoss/ibiza.git"},"bugs":{"url":"https://github.com/joelmoss/ibiza/issues"},"keywords":["react","state","proxy"],"type":"module","source":"src/index.js","main":"dist/ibiza.cjs","module":"dist/ibiza.module.js","unpkg":"dist/ibiza.umd.js","exports":{"require":"./dist/ibiza.cjs","default":"./dist/ibiza.modern.js"},"sideEffects":false,"eslintConfig":{"extends":["eslint:recommended","plugin:react/recommended","plugin:react-hooks/recommended","plugin:prettier/recommended"],"settings":{"react":{"version":"detect"}},"env":{"browser":true,"node":false,"es6":true},"parserOptions":{"ecmaVersion":"latest","sourceType":"module","ecmaFeatures":{"jsx":true}},"rules":{"react/prop-types":0},"overrides":[{"files":["test/**"],"extends":["plugin:jest/recommended","plugin:testing-library/react","plugin:jest/style"],"rules":{"jest/expect-expect":["warn",{"assertFunctionNames":["expect","screen.findByText","screen.getByText"]}]}}]},"size-limit":[{"name":"useIbiza","path":"./src/index.js","import":"{ useIbiza }","limit":"1 s"},{"name":"store","path":"./src/index.js","import":"{ store }","limit":"1 s"},{"name":"createModel","path":"./src/index.js","import":"{ createModel }","limit":"1 s"},{"name":"unproxiedStateOf","path":"./src/index.js","import":"{ unproxiedStateOf }","limit":"1 s"},{"name":"freeze","path":"./src/index.js","import":"{ freeze }","limit":"1 s"}],"prettier":{"trailingComma":"none","printWidth":100,"semi":false,"singleQuote":true,"arrowParens":"avoid"},"peerDependencies":{"react":">=17"},"devDependencies":{"@size-limit/preset-big-lib":"^7.0.1","@swc/core":"^1.2.144","@swc/jest":"^0.2.17","@testing-library/dom":"^8.14.0","@testing-library/jest-dom":"^5.15.0","@testing-library/react":"^13.0.0","@testing-library/user-event":"^14.2.1","cross-fetch":"^3.1.4","eslint":"^8.18.0","eslint-config-prettier":"^8.5.0","eslint-plugin-jest":"^26.5.3","eslint-plugin-prettier":"^4.0.0","eslint-plugin-react":"^7.30.0","eslint-plugin-react-hooks":"^4.6.0","eslint-plugin-testing-library":"^5.5.1","fetch-mock-jest":"^1.5.1","ibiza":"link:./ibiza","jest":"^28.1.0","jest-environment-jsdom":"^28.1.0","microbundle":"^0.15.0","msw":"^0.42","prettier":"^2.7.1","react":"^18.2.0","react-dom":"^18.2.0","react-error-boundary":"^3.1.4","rimraf":"^3.0.2","size-limit":"^7.0.0"},"dependencies":{"fast-equals":"^4.0.0","micro-memoize":"^4.0.9","use-sync-external-store":"^1.2.0"},"scripts":{"clean":"rimraf dist","test":"jest","build":"microbundle --jsx React.createElement","dev":"microbundle watch --jsx React.createElement --compress false","size":"microbundle && size-limit","lint":"eslint src test --ext .jsx --ext .js"},"readme":"# Ibiza - React State Management for Party Animals\n\nIbiza gets out of your way and simply lets you read and write state as you would with regular\nJavascript assignment. It maintains a global state object and is smart enough to know when to\nrerender your components based on state usage and modification.\n\n## `useIbiza()` ✨\n\nA component calls the `useIbiza` React hook, which returns the store state as a JS Proxy object.\nThis Proxy records when a state property is accessed or \"used\". Then when that property is mutated,\nthe component is rerendered.\n\nThis means that you can mutate your state in any way, but your component will only rerender if you\nmutate state that you have used.\n\nThe following component will rerender when the button is clicked, because `name` has changed.\n\n```jsx\nimport { useIbiza } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n      <button onClick={() => void (state.name = 'Joel')}></button>\n    </div>\n  )\n}\n```\n\nThe following component will not rerender when the button is clicked, because even though `age` has\nbeen mutated, it is not actually being used within the component.\n\n```jsx\nimport { useIbiza } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n      <button onClick={() => void (state.age = 44)}></button>\n    </div>\n  )\n}\n```\n\nState can be mutated from anywhere - not just from within a component:\n\n```js\nimport { useIbiza, store } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n    </div>\n  )\n}\n\n// <App> component will re-render when this line executes, as `name` has changed.\nstore.state.name = 'Ash'\n```\n\n### Initial State\n\nYou can pass some initial state to `useIbiza` which will be merged with existing state in the Ibiza\nstore.\n\n```jsx\nconst App = () => {\n  const state = useIbiza({ user: { name: 'Joel' } })\n\n  return <h1>Hello {state.user.name}</h1>\n}\n```\n\nThis is safe to include in the body of your component, as it will only be merged into the store on\nfirst render.\n\n### Slicing\n\nIbiza supports deeply nested objects, allowing you to design the shape of your state any way you\nlike. To help you work with such nested state, the `useIbiza` hook supports slicing.\n\nThe following example assumes you have an existing state object:\n\n```javascript\n{\n  user: {\n    name: 'Joel',\n    partner: {\n      name: 'Sam',\n    }\n  }\n}\n```\n\nPass a string to `useIbiza` to fetch a specific slice of state. The string should be the path to the\nobject that you want.\n\n```jsx\nconst App = () => {\n  const partner = useIbiza('user.partner')\n\n  return (\n    <div>\n      <h1>Hello {partner.name}</h1>\n      <button onClick={() => void (partner.name = 'Bob')}></button>\n    </div>\n  )\n}\n```\n\nNote that slicing is really only supported as a convenience, and will not generally help with\nperformance.\n\n## `createModel()`\n\nIbiza is at its most powerful when working with models. They provide reusability and flexibility.\n\nCreate a model using the `createModel` helper, where the first argument is the model name, and the\nsecond argument is the initial model state as a plain object.\n\n```javascript\n// model.js\n\nexport default createModel('user', {\n  firstName: 'Joel',\n  lastName: 'Moss',\n  children: [{ firstName: 'Ash' }, { firstName: 'Elijah' }, { firstName: 'Eve' }]\n})\n```\n\n`createModel` returns a hook which you can use. You can now import your model anywhere:\n\n```jsx\n// app.jsx\n\nimport useModel from './model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <div>\n      <h1>Hello {user.firstName}</h1>\n      <ul>\n        {user.children.map((child, i) => (\n          <li key={i}>{child.firstName}</li>\n        ))}\n      </ul>\n    </div>\n  )\n}\n```\n\n### Initial State\n\nSometimes you want to be able to define your model with some initial state that could be provided\ndynamically. For example, from component props or some other parameters.\n\n`createModel` can accept a function as its second argument. This function will be called on\ninitialisation with two arguments; the current `state` and any `props` passed to it when its hook is\nfirst called.\n\n```javascript\n// model.js\n\nexport default createModel('user', (state, props) => ({\n  firstName: 'Joel',\n  lastName: 'Moss'\n  ...props\n}))\n```\n\n```jsx\n// app.jsx\n\nimport useModel from './model'\n\nconst App = ({ yearOfBirth }) => {\n  const user = useModel({ yearOfBirth })\n\n  return (\n    <div>\n      <h1>\n        Hello {user.firstName}, you were born in {user.yearOfBirth}.\n      </h1>\n    </div>\n  )\n}\n```\n\n### Functions\n\nYou can use regular function in your model. They accept the current state as the first argument, and\n`this` will also be the current state (as long as you don't use hash rocket functions).\n\n```jsx\nconst App = () => {\n  const state = useIbiza({\n    count: 0,\n    increment: state => {\n      ++state.count\n    },\n    decrement() {\n      ++this.count\n    }\n  })\n\n  return (\n    <>\n      <h1>Count = {state.count}</h1>\n      <button onClick={state.increment}>Increment</button>\n      <button onClick={state.decrement}>Decrement</button>\n    </>\n  )\n}\n```\n\nWhen reading/writing state within a function, `this` responds to the state at the level where the\nfunction sits. This means that if the function is deeply nested, `this` will not include state lower\ndown.\n\nTo solve this, you can call `this.$model` to access your model, or `this.$root` to access the root\nof the store state.\n\n```javascript\nuseIbiza({\n  deepstate: {\n    user: {\n      name: 'Joel',\n      partner: {\n        name: 'Sam',\n\n        get partner() {\n          // `this` refers to 'deepstate.user.partner'.\n          // `this.$model` refers to 'deepstate.user'.\n          // `this.$root` is the whole store state.\n          return this.$model.name\n        }\n      }\n    }\n  }\n})\n```\n\nFunctions accept any number of arguments just like regular functions do, but don't forget that the\nfirst argument is always the state.\n\n```jsx\nconst App = () => {\n  const user = useIbiza({\n    children: [],\n    addChild(state, firstName, lastName) {\n      state.children.push({ firstName, lastName }) // or `this.children.push(...)`\n    }\n  })\n\n  return (\n    <>\n      <ul>\n        {user.children.map((child, i) => (\n          <li key={i}>\n            {child.firstName} {child.lastName}\n          </li>\n        ))}\n      </ul>\n      <button onClick={() => user.addChild('Ash', 'Moss')}></button>\n    </>\n  )\n}\n```\n\nNote that used state is not tracked within functions. This avoids unnecessary component re-rendering\nwhen state changes that is used by a function. The function will always use the latest state anyway,\nso no need to track the state that it uses.\n\nThis does however, mean that you should not call functions during rendering - use a getter instead.\n\n### Getters and Setters\n\nIbiza supports Javascript getters and setters in your state and models.\n\n```javascript\nexport default createModel('user', {\n  firstName: 'Joel',\n  lastName: 'Moss',\n\n  get fullName() {\n    // You can read/write to your state via `this`.\n    return `${this.firstName} ${this.lastName}`\n  },\n\n  set fullName(value) {\n    const [firstName, lastName] = value.split(' ')\n\n    this.firstName = firstName\n    this.lastName = lastName\n  }\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <h1>Hello {user.fullName}</h1>\n      <button onClick={() => void (user.fullName = 'Bob Bones')}></button>\n    </>\n  )\n}\n```\n\n### Async Functions\n\nFunctions can be async and/or return Promises, and support React's Suspense by default.\n\n```javascript\nexport default createModel('user', {\n  name: 'Joel',\n\n  async doSomething() {\n    return await someAsyncAction()\n  }\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <h1>Hello {user.fullName}</h1>\n      <button onClick={user.doSomething}></button>\n    </>\n  )\n}\n```\n\n### URL Models\n\nBecause reading and writing to/from the server is so common, Ibiza has support to make this easy\nwith URL Models, similar to react-query. Simply use a valid and relative URL as your model name or\nslice.\n\nThe following will fetch the user from the server at `/user`, suspending the component while it does\nso. The data is fetched only when it does not exist in the store.\n\n```jsx\nconst App = () => {\n  const user = useIbiza('/user')\n\n  return <h1>Hello {user.name}</h1>\n}\n```\n\nYou can safely mutate your model, as all mutations will remain local.\n\nYou can write your model state back to the server. It the server responds with JSON, the model will\nbe updated with that response.\n\n```jsx\nconst App = () => {\n  const user = useIbiza('/user')\n\n  const renameUser = async () => {\n    await user.save({ body: { name: 'Bob' } })\n  }\n\n  return (\n    <>\n      <h1>Hello {user.name}</h1>\n      <button onClick={renameUser}></button>\n    </>\n  )\n}\n```\n\nURL Models can also be defined with `createModel`, and accept the same arguments:\n\n```javascript\nexport default createModel('/user')\n```\n\n`createModel` returns a hook which you can use. You can now import your model anywhere:\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return <h1>Hello {user.firstName}</h1>\n}\n```\n\nAdditionally, URL models accept a `fetcher` option, which when provided, will be used as the fetch\nfunction for the model:\n\n```javascript\nexport default createModel('/user', {}, { fetcher: myFetchFunction })\n```\n\n## `createContextModel()`\n\nWrap your component in the `IbizaProvider` higher order component, and instead of `createModel()`,\ncreate your model with `createContextModel()` function. The model will automatically be given a\nunique name specific to the wrapped components in IbizaProvider. Just pass the model definition as\nthe first argument. It accepts the same options as `createModel()` for the second argument.\n\n```jsx\nconst useModel = createContextModel(() => ({\n  // Your model definition...\n  name: 'Awesome!'\n}))\n\nconst App = () => {\n  return (\n    <IbizaProvider>\n      <MyComponent />\n    </IbizaProvider>\n  );\n};\n\nconst MyComponent = () => {\n  const model = useModel()\n\n  return <h1>My model is {model.name}</h1>\n};\n```\n\nEach instance of IbizaProvider will use its own state.\n\n```jsx\nconst useFirstModel = createContextModel(() => ({\n  name: 'FIRST!'\n}))\n\nconst useSecondModel = createContextModel(() => ({\n  name: 'SECOND!'\n}))\n\nconst App = () => {\n  return (\n    <>\n      <IbizaProvider>\n        <MyFirstComponent />\n      </IbizaProvider>\n      <IbizaProvider>\n        <MySecondComponent />\n      </IbizaProvider>\n    </>\n  );\n};\n\nconst MyFirstComponent = () => {\n  const model = useFirstModel();\n\n  return <h1>My model is {model.name}</h1>; // My model is FIRST!\n};\n\nconst MySecondComponent = () => {\n  const model = useSecondModel()\n\n  return <h1>My model is {model.name}</h1> // My model is SECOND!\n};\n```\n\n## How Does Ibiza Work?\n\nIt's all thanks to the magic of Unicorns! 🦄\n\n...actually, I lie. In reality, the magic is courtesy of [JavaScript Proxies](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy).\n\nAnytime you call `useIbiza` in a component, a Proxy of the store state is returned. Reading\nproperties from this proxy is recorded, and each property is tracked as being used in the component.\nWe call this the Hook Proxy, as it is specific to the instance of the `useIbiza` hook, and therefore\nthe component it is used within.\n\nYou can read and write from/to the Hook Proxy, as you would any JavaScript object. Reading, or using\na property, will cause the component to re-render when the property's value is mutated. And mutating\na property value will cause any component that has read the same property, to re-render.\n\nThe Hook Proxy wraps the Store Proxy, which contains the actual Ibiza global state. As with the Hook\nProxy, the Store Proxy can be read and written to, and components that have used the state will\nre-render upon mutation. This means you can mutate the state via the Hook Proxy and/or the Store\nProxy. The Store Proxy does not track property usage.\n","readmeFilename":"README.md","_id":"ibiza@2.0.0-alpha.9","_integrity":"sha512-rKtBwPExFLf7YskGPL4PsEg4PHTTnZo/4SMOukxCVli9E/g+w5vWAeoCLLd7p9/N1ZkZnmoGg8jZoaH6B76Mog==","_resolved":"/private/var/folders/3b/b6pthvr51cg1755k2jxx8www0000gn/T/93905bc95d6fe87cf78a6c22652237ba/ibiza-2.0.0-alpha.9.tgz","_from":"file:ibiza-2.0.0-alpha.9.tgz","_nodeVersion":"18.6.0","_npmVersion":"8.13.2","dist":{"integrity":"sha512-rKtBwPExFLf7YskGPL4PsEg4PHTTnZo/4SMOukxCVli9E/g+w5vWAeoCLLd7p9/N1ZkZnmoGg8jZoaH6B76Mog==","shasum":"b165ea29ab4e7ffcc97d40586690a802238b754a","tarball":"https://registry.npmjs.org/ibiza/-/ibiza-2.0.0-alpha.9.tgz","fileCount":10,"unpackedSize":334816,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIC1xUmSz8GA6he2bcQXCo/aH117rlzmVZybLkZgeLZx2AiEAmNx7g2TJMoZP/UbyiD+oYADtQWNw7d8Qnm8c6aDHFVE="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJi4UYcACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpmXA//St/P+JQYdy0eDkdaVukFj7t1R95pYWM9z4bpKYb3nysPuQAw\r\naoPr9CIdUzPhpCN1/D0KYw2UjSYWyBhHiibMN0F/G7kRqgdYIXRl1hc6S21Z\r\n9UErSZHSZMKuxmZS0SiSJ5wOhMGMAwphxluYWUa5csXswfuBw8m9SBRpd9nD\r\nNrNB0JFGqzXLLQegPJUWtDAXLxzESn593Am4RbYCQSQcrDqzzmMRFvqEtpuQ\r\n1fdRF/jPo6jy/yHBysQQlI3UxzEafpHTbmPk9ZQTkrZbJuqQYRq9j1xEa+8p\r\nvdKkOhmujL9NwD1fpxkwVha5jaN9npZll6EPgWNpdH7k59NZfWm2/52ywwtW\r\nTAPvP1nU3NcJAO33DMdadVOJvSQXPuKHtTFT4/opwZKf6syZiAXXStrf6+Mr\r\nHaW4AfFzxTmQY06dNa1MEJHiRVAgJ5X8+Yf4wWZRWy8hJRCrP0tJQqMa8EWz\r\nElZG4t2THo4sXTNfKJxwX5qAsFkc76Xm8B0vsb5rm7ii7EHa/gIYWILwU0qc\r\nmbFmLLdd3KkcTlKG/HVTUg7Af1X3fiH3Eyg1uiqCQzeRwkCKhGeVNoI39Bc3\r\nLvIweK72DK8wFcdToCkZHB1BGaIeYixmzzFqW1NmWXSNLeOA66HEHV5mxs3B\r\nuR6iGWhawFiX6hicr1nclB+DctmLUH5acjo=\r\n=8P94\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"joelmoss","email":"joel@developwithstyle.com"},"directories":{},"maintainers":[{"name":"joelmoss","email":"joel@developwithstyle.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ibiza_2.0.0-alpha.9_1658930716471_0.7008138345824508"},"_hasShrinkwrap":false},"2.0.0-alpha.10":{"name":"ibiza","author":{"name":"Joel Moss"},"version":"2.0.0-alpha.10","description":"React State Management for Party Animals","license":"MIT","homepage":"https://github.com/joelmoss/ibiza","repository":{"type":"git","url":"git+https://github.com/joelmoss/ibiza.git"},"bugs":{"url":"https://github.com/joelmoss/ibiza/issues"},"keywords":["react","state","proxy"],"type":"module","source":"src/index.js","main":"dist/ibiza.cjs","module":"dist/ibiza.module.js","unpkg":"dist/ibiza.umd.js","exports":{"require":"./dist/ibiza.cjs","default":"./dist/ibiza.modern.js"},"sideEffects":false,"eslintConfig":{"extends":["eslint:recommended","plugin:react/recommended","plugin:react-hooks/recommended","plugin:prettier/recommended"],"settings":{"react":{"version":"detect"}},"env":{"browser":true,"node":false,"es6":true},"parserOptions":{"ecmaVersion":"latest","sourceType":"module","ecmaFeatures":{"jsx":true}},"rules":{"react/prop-types":0},"overrides":[{"files":["test/**"],"extends":["plugin:jest/recommended","plugin:testing-library/react","plugin:jest/style"],"rules":{"jest/expect-expect":["warn",{"assertFunctionNames":["expect","screen.findByText","screen.getByText"]}]}}]},"size-limit":[{"name":"useIbiza","path":"./src/index.js","import":"{ useIbiza }","limit":"1 s"},{"name":"store","path":"./src/index.js","import":"{ store }","limit":"1 s"},{"name":"createModel","path":"./src/index.js","import":"{ createModel }","limit":"1 s"},{"name":"unproxiedStateOf","path":"./src/index.js","import":"{ unproxiedStateOf }","limit":"1 s"},{"name":"freeze","path":"./src/index.js","import":"{ freeze }","limit":"1 s"}],"prettier":{"trailingComma":"none","printWidth":100,"semi":false,"singleQuote":true,"arrowParens":"avoid"},"peerDependencies":{"react":">=17"},"devDependencies":{"@size-limit/preset-big-lib":"^7.0.1","@swc/core":"^1.2.144","@swc/jest":"^0.2.17","@testing-library/dom":"^8.14.0","@testing-library/jest-dom":"^5.15.0","@testing-library/react":"^13.0.0","@testing-library/user-event":"^14.2.1","cross-fetch":"^3.1.4","eslint":"^8.18.0","eslint-config-prettier":"^8.5.0","eslint-plugin-jest":"^26.5.3","eslint-plugin-prettier":"^4.0.0","eslint-plugin-react":"^7.30.0","eslint-plugin-react-hooks":"^4.6.0","eslint-plugin-testing-library":"^5.5.1","fetch-mock-jest":"^1.5.1","ibiza":"link:./ibiza","jest":"^28.1.0","jest-environment-jsdom":"^28.1.0","microbundle":"^0.15.0","msw":"^0.42","prettier":"^2.7.1","react":"^18.2.0","react-dom":"^18.2.0","react-error-boundary":"^3.1.4","rimraf":"^3.0.2","size-limit":"^7.0.0"},"dependencies":{"fast-equals":"^4.0.0","micro-memoize":"^4.0.9","use-sync-external-store":"^1.2.0"},"scripts":{"clean":"rimraf dist","test":"jest","build":"microbundle --jsx React.createElement","dev":"microbundle watch --jsx React.createElement --compress false","size":"microbundle && size-limit","lint":"eslint src test --ext .jsx --ext .js"},"readme":"# Ibiza - React State Management for Party Animals\n\nIbiza gets out of your way and simply lets you read and write state as you would with regular\nJavascript assignment. It maintains a global state object and is smart enough to know when to\nrerender your components based on state usage and modification.\n\n## `useIbiza()` ✨\n\nA component calls the `useIbiza` React hook, which returns the store state as a JS Proxy object.\nThis Proxy records when a state property is accessed or \"used\". Then when that property is mutated,\nthe component is rerendered.\n\nThis means that you can mutate your state in any way, but your component will only rerender if you\nmutate state that you have used.\n\nThe following component will rerender when the button is clicked, because `name` has changed.\n\n```jsx\nimport { useIbiza } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n      <button onClick={() => void (state.name = 'Joel')}></button>\n    </div>\n  )\n}\n```\n\nThe following component will not rerender when the button is clicked, because even though `age` has\nbeen mutated, it is not actually being used within the component.\n\n```jsx\nimport { useIbiza } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n      <button onClick={() => void (state.age = 44)}></button>\n    </div>\n  )\n}\n```\n\nState can be mutated from anywhere - not just from within a component:\n\n```js\nimport { useIbiza, store } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n    </div>\n  )\n}\n\n// <App> component will re-render when this line executes, as `name` has changed.\nstore.state.name = 'Ash'\n```\n\n### Initial State\n\nYou can pass some initial state to `useIbiza` which will be merged with existing state in the Ibiza\nstore.\n\n```jsx\nconst App = () => {\n  const state = useIbiza({ user: { name: 'Joel' } })\n\n  return <h1>Hello {state.user.name}</h1>\n}\n```\n\nThis is safe to include in the body of your component, as it will only be merged into the store on\nfirst render.\n\n### Slicing\n\nIbiza supports deeply nested objects, allowing you to design the shape of your state any way you\nlike. To help you work with such nested state, the `useIbiza` hook supports slicing.\n\nThe following example assumes you have an existing state object:\n\n```javascript\n{\n  user: {\n    name: 'Joel',\n    partner: {\n      name: 'Sam',\n    }\n  }\n}\n```\n\nPass a string to `useIbiza` to fetch a specific slice of state. The string should be the path to the\nobject that you want.\n\n```jsx\nconst App = () => {\n  const partner = useIbiza('user.partner')\n\n  return (\n    <div>\n      <h1>Hello {partner.name}</h1>\n      <button onClick={() => void (partner.name = 'Bob')}></button>\n    </div>\n  )\n}\n```\n\nNote that slicing is really only supported as a convenience, and will not generally help with\nperformance.\n\n## `createModel()`\n\nIbiza is at its most powerful when working with models. They provide reusability and flexibility.\n\nCreate a model using the `createModel` helper, where the first argument is the model name, and the\nsecond argument is the initial model state as a plain object.\n\n```javascript\n// model.js\n\nexport default createModel('user', {\n  firstName: 'Joel',\n  lastName: 'Moss',\n  children: [{ firstName: 'Ash' }, { firstName: 'Elijah' }, { firstName: 'Eve' }]\n})\n```\n\n`createModel` returns a hook which you can use. You can now import your model anywhere:\n\n```jsx\n// app.jsx\n\nimport useModel from './model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <div>\n      <h1>Hello {user.firstName}</h1>\n      <ul>\n        {user.children.map((child, i) => (\n          <li key={i}>{child.firstName}</li>\n        ))}\n      </ul>\n    </div>\n  )\n}\n```\n\n### Initial State\n\nSometimes you want to be able to define your model with some initial state that could be provided\ndynamically. For example, from component props or some other parameters.\n\n`createModel` can accept a function as its second argument. This function will be called on\ninitialisation with two arguments; the current `state` and any `props` passed to it when its hook is\nfirst called.\n\n```javascript\n// model.js\n\nexport default createModel('user', (state, props) => ({\n  firstName: 'Joel',\n  lastName: 'Moss'\n  ...props\n}))\n```\n\n```jsx\n// app.jsx\n\nimport useModel from './model'\n\nconst App = ({ yearOfBirth }) => {\n  const user = useModel({ yearOfBirth })\n\n  return (\n    <div>\n      <h1>\n        Hello {user.firstName}, you were born in {user.yearOfBirth}.\n      </h1>\n    </div>\n  )\n}\n```\n\n### Functions\n\nYou can use regular function in your model. They accept the current state as the first argument, and\n`this` will also be the current state (as long as you don't use hash rocket functions).\n\n```jsx\nconst App = () => {\n  const state = useIbiza({\n    count: 0,\n    increment: state => {\n      ++state.count\n    },\n    decrement() {\n      ++this.count\n    }\n  })\n\n  return (\n    <>\n      <h1>Count = {state.count}</h1>\n      <button onClick={state.increment}>Increment</button>\n      <button onClick={state.decrement}>Decrement</button>\n    </>\n  )\n}\n```\n\nWhen reading/writing state within a function, `this` responds to the state at the level where the\nfunction sits. This means that if the function is deeply nested, `this` will not include state lower\ndown.\n\nTo solve this, you can call `this.$model` to access your model, or `this.$root` to access the root\nof the store state.\n\n```javascript\nuseIbiza({\n  deepstate: {\n    user: {\n      name: 'Joel',\n      partner: {\n        name: 'Sam',\n\n        get partner() {\n          // `this` refers to 'deepstate.user.partner'.\n          // `this.$model` refers to 'deepstate.user'.\n          // `this.$root` is the whole store state.\n          return this.$model.name\n        }\n      }\n    }\n  }\n})\n```\n\nFunctions accept any number of arguments just like regular functions do, but don't forget that the\nfirst argument is always the state.\n\n```jsx\nconst App = () => {\n  const user = useIbiza({\n    children: [],\n    addChild(state, firstName, lastName) {\n      state.children.push({ firstName, lastName }) // or `this.children.push(...)`\n    }\n  })\n\n  return (\n    <>\n      <ul>\n        {user.children.map((child, i) => (\n          <li key={i}>\n            {child.firstName} {child.lastName}\n          </li>\n        ))}\n      </ul>\n      <button onClick={() => user.addChild('Ash', 'Moss')}></button>\n    </>\n  )\n}\n```\n\nNote that used state is not tracked within functions. This avoids unnecessary component re-rendering\nwhen state changes that is used by a function. The function will always use the latest state anyway,\nso no need to track the state that it uses.\n\nThis does however, mean that you should not call functions during rendering - use a getter instead.\n\n### Getters and Setters\n\nIbiza supports Javascript getters and setters in your state and models.\n\n```javascript\nexport default createModel('user', {\n  firstName: 'Joel',\n  lastName: 'Moss',\n\n  get fullName() {\n    // You can read/write to your state via `this`.\n    return `${this.firstName} ${this.lastName}`\n  },\n\n  set fullName(value) {\n    const [firstName, lastName] = value.split(' ')\n\n    this.firstName = firstName\n    this.lastName = lastName\n  }\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <h1>Hello {user.fullName}</h1>\n      <button onClick={() => void (user.fullName = 'Bob Bones')}></button>\n    </>\n  )\n}\n```\n\n### Async Functions\n\nFunctions can be async and/or return Promises, and support React's Suspense by default.\n\n```javascript\nexport default createModel('user', {\n  name: 'Joel',\n\n  async doSomething() {\n    return await someAsyncAction()\n  }\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <h1>Hello {user.fullName}</h1>\n      <button onClick={user.doSomething}></button>\n    </>\n  )\n}\n```\n\n### URL Models\n\nBecause reading and writing to/from the server is so common, Ibiza has support to make this easy\nwith URL Models, similar to react-query. Simply use a valid and relative URL as your model name or\nslice.\n\nThe following will fetch the user from the server at `/user`, suspending the component while it does\nso. The data is fetched only when it does not exist in the store.\n\n```jsx\nconst App = () => {\n  const user = useIbiza('/user')\n\n  return <h1>Hello {user.name}</h1>\n}\n```\n\nYou can safely mutate your model, as all mutations will remain local.\n\nYou can write your model state back to the server. It the server responds with JSON, the model will\nbe updated with that response.\n\n```jsx\nconst App = () => {\n  const user = useIbiza('/user')\n\n  const renameUser = async () => {\n    await user.save({ body: { name: 'Bob' } })\n  }\n\n  return (\n    <>\n      <h1>Hello {user.name}</h1>\n      <button onClick={renameUser}></button>\n    </>\n  )\n}\n```\n\nURL Models can also be defined with `createModel`, and accept the same arguments:\n\n```javascript\nexport default createModel('/user')\n```\n\n`createModel` returns a hook which you can use. You can now import your model anywhere:\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return <h1>Hello {user.firstName}</h1>\n}\n```\n\nAdditionally, URL models accept a `fetcher` option, which when provided, will be used as the fetch\nfunction for the model:\n\n```javascript\nexport default createModel('/user', {}, { fetcher: myFetchFunction })\n```\n\n## `createContextModel()`\n\nWrap your component in the `IbizaProvider` higher order component, and instead of `createModel()`,\ncreate your model with `createContextModel()` function. The model will automatically be given a\nunique name specific to the wrapped components in IbizaProvider. Just pass the model definition as\nthe first argument. It accepts the same options as `createModel()` for the second argument.\n\n```jsx\nconst useModel = createContextModel(() => ({\n  // Your model definition...\n  name: 'Awesome!'\n}))\n\nconst App = () => {\n  return (\n    <IbizaProvider>\n      <MyComponent />\n    </IbizaProvider>\n  );\n};\n\nconst MyComponent = () => {\n  const model = useModel()\n\n  return <h1>My model is {model.name}</h1>\n};\n```\n\nEach instance of IbizaProvider will use its own state.\n\n```jsx\nconst useFirstModel = createContextModel(() => ({\n  name: 'FIRST!'\n}))\n\nconst useSecondModel = createContextModel(() => ({\n  name: 'SECOND!'\n}))\n\nconst App = () => {\n  return (\n    <>\n      <IbizaProvider>\n        <MyFirstComponent />\n      </IbizaProvider>\n      <IbizaProvider>\n        <MySecondComponent />\n      </IbizaProvider>\n    </>\n  );\n};\n\nconst MyFirstComponent = () => {\n  const model = useFirstModel();\n\n  return <h1>My model is {model.name}</h1>; // My model is FIRST!\n};\n\nconst MySecondComponent = () => {\n  const model = useSecondModel()\n\n  return <h1>My model is {model.name}</h1> // My model is SECOND!\n};\n```\n\n## How Does Ibiza Work?\n\nIt's all thanks to the magic of Unicorns! 🦄\n\n...actually, I lie. In reality, the magic is courtesy of [JavaScript Proxies](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy).\n\nAnytime you call `useIbiza` in a component, a Proxy of the store state is returned. Reading\nproperties from this proxy is recorded, and each property is tracked as being used in the component.\nWe call this the Hook Proxy, as it is specific to the instance of the `useIbiza` hook, and therefore\nthe component it is used within.\n\nYou can read and write from/to the Hook Proxy, as you would any JavaScript object. Reading, or using\na property, will cause the component to re-render when the property's value is mutated. And mutating\na property value will cause any component that has read the same property, to re-render.\n\nThe Hook Proxy wraps the Store Proxy, which contains the actual Ibiza global state. As with the Hook\nProxy, the Store Proxy can be read and written to, and components that have used the state will\nre-render upon mutation. This means you can mutate the state via the Hook Proxy and/or the Store\nProxy. The Store Proxy does not track property usage.\n","readmeFilename":"README.md","_id":"ibiza@2.0.0-alpha.10","_integrity":"sha512-E06/WuCw6fYWYzNA2gGrhV81w02TMgqqIRlDhAbVnE3VSr+xY5GnU80fA81Fz6T2cCa3Tz1lF2nMpLaddxeM6Q==","_resolved":"/private/var/folders/3b/b6pthvr51cg1755k2jxx8www0000gn/T/1479cd1e0ce5d9b69bd171fff22c598f/ibiza-2.0.0-alpha.10.tgz","_from":"file:ibiza-2.0.0-alpha.10.tgz","_nodeVersion":"18.8.0","_npmVersion":"8.18.0","dist":{"integrity":"sha512-E06/WuCw6fYWYzNA2gGrhV81w02TMgqqIRlDhAbVnE3VSr+xY5GnU80fA81Fz6T2cCa3Tz1lF2nMpLaddxeM6Q==","shasum":"77e80ca02e49afd84c1683e07914004eea2d6bf5","tarball":"https://registry.npmjs.org/ibiza/-/ibiza-2.0.0-alpha.10.tgz","fileCount":10,"unpackedSize":335753,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAzztSyutML54p1Ve0TXpMau0exQcdsccR7Rm6ToBUrjAiEAjQMlvXeeZWe6l4BVCf8H4DB5QfItMUIDMXaJ6sLX6Ko="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjFcPrACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrBsw/+N6Dd5h5GiZ9fZtvA5eeLVHl2JrUe4lq76f8XBClUOSt2tC4M\r\notIo9ENavRUCx8q8KExSbWFIQY2oSqgVgWGKRQNeZtmTYY9zbZ9lqUtrsYJN\r\nHoTfvnq+zt8Pbm4jY3HdLdzI1pd0SLHkVB7CTzkMggo8Z1+BTI8ey4nq/AOS\r\nPXO1SgC/gF+7aJ7FzlmIC01ayFqkZ6omCLj705lXpeJQjwlDlQ0tV1ckQdxs\r\n56LZGAm6F8qBzOfyI/Vesp4BDTuZgM9AzQ4qNEThAekxpgpwlaBjgHWbz8ey\r\nuOu6ISMivtnLpuF086BC/6vcjKiVFfcds6rB9bt9g30KTd3s7vq5ejCudCvX\r\nADb5mEc3wL8Cy+agUcjSW8c90sj+i2xmQu/KEUNjj529KeGfkQ8pzSjuc3g9\r\n8Cc0AdWAQjO67YS7x37Ql5KzuWpp6EJsjXx247yWp0PsZDruoKC9QBC7P0yL\r\nJiVnc+OCjODdpZU/8fDWZY3I+g4Bg7zGm18dcn+fEmoW2v3GgYglKEL0hw4H\r\nnPgD1rHi1gvCRR9ST04xpBWpHnCYHX1+5d2g0zalaIMz9yIV+QgClguhctc7\r\nvKJpe5YTcnUsbvsQvZg0Y58mYOkjbeFj7jDcuPTRseAAUmN8JZ9ehTftxh6C\r\nlmyQDS4Rjj5LjsxIv2YP1+5OrRg72naOoPk=\r\n=ufD9\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"joelmoss","email":"joel@developwithstyle.com"},"directories":{},"maintainers":[{"name":"joelmoss","email":"joel@developwithstyle.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ibiza_2.0.0-alpha.10_1662370794834_0.22475245586821901"},"_hasShrinkwrap":false},"2.0.0-alpha.11":{"name":"ibiza","author":{"name":"Joel Moss"},"version":"2.0.0-alpha.11","description":"React State Management for Party Animals","license":"MIT","homepage":"https://github.com/joelmoss/ibiza","repository":{"type":"git","url":"git+https://github.com/joelmoss/ibiza.git"},"bugs":{"url":"https://github.com/joelmoss/ibiza/issues"},"keywords":["react","state","proxy"],"type":"module","source":"src/index.js","main":"dist/ibiza.cjs","module":"dist/ibiza.module.js","unpkg":"dist/ibiza.umd.js","exports":{"require":"./dist/ibiza.cjs","default":"./dist/ibiza.modern.js"},"sideEffects":false,"eslintConfig":{"extends":["eslint:recommended","plugin:react/recommended","plugin:react-hooks/recommended","plugin:prettier/recommended"],"settings":{"react":{"version":"detect"}},"env":{"browser":true,"node":false,"es6":true},"parserOptions":{"ecmaVersion":"latest","sourceType":"module","ecmaFeatures":{"jsx":true}},"rules":{"react/prop-types":0},"overrides":[{"files":["test/**"],"extends":["plugin:jest/recommended","plugin:testing-library/react","plugin:jest/style"],"rules":{"jest/expect-expect":["warn",{"assertFunctionNames":["expect","screen.findByText","screen.getByText"]}]}}]},"size-limit":[{"name":"useIbiza","path":"./src/index.js","import":"{ useIbiza }","limit":"1 s"},{"name":"store","path":"./src/index.js","import":"{ store }","limit":"1 s"},{"name":"createModel","path":"./src/index.js","import":"{ createModel }","limit":"1 s"},{"name":"unproxiedStateOf","path":"./src/index.js","import":"{ unproxiedStateOf }","limit":"1 s"},{"name":"freeze","path":"./src/index.js","import":"{ freeze }","limit":"1 s"}],"prettier":{"trailingComma":"none","printWidth":100,"semi":false,"singleQuote":true,"arrowParens":"avoid"},"peerDependencies":{"react":">=17"},"devDependencies":{"@size-limit/preset-big-lib":"^8.1","@swc/core":"^1.2.144","@swc/jest":"^0.2.17","@testing-library/dom":"^8.14.0","@testing-library/jest-dom":"^5.15.0","@testing-library/react":"^13.0.0","@testing-library/user-event":"^14.2.1","cross-fetch":"^3.1.4","eslint":"^8.18.0","eslint-config-prettier":"^8.5.0","eslint-plugin-jest":"^27.0","eslint-plugin-prettier":"^4.0.0","eslint-plugin-react":"^7.30.0","eslint-plugin-react-hooks":"^4.6.0","eslint-plugin-testing-library":"^5.5.1","fetch-mock-jest":"^1.5.1","ibiza":"link:./ibiza","jest":"^29.1","jest-environment-jsdom":"^29.1.0","microbundle":"^0.15.0","msw":"^0.47","prettier":"^2.7.1","react":"^18.2.0","react-dom":"^18.2.0","react-error-boundary":"^3.1.4","rimraf":"^3.0.2","size-limit":"^8.1.0"},"dependencies":{"fast-equals":"^4.0.0","micro-memoize":"^4.0.9","use-sync-external-store":"^1.2.0"},"scripts":{"clean":"rimraf dist","test":"jest","build":"microbundle --jsx React.createElement","dev":"microbundle watch --jsx React.createElement --compress false","size":"microbundle && size-limit","lint":"eslint src test --ext .jsx --ext .js"},"readme":"# Ibiza - React State Management for Party Animals\n\nIbiza gets out of your way and simply lets you read and write state as you would with regular\nJavascript assignment. It maintains a global state object and is smart enough to know when to\nrerender your components based on state usage and modification.\n\n## `useIbiza()` ✨\n\nA component calls the `useIbiza` React hook, which returns the store state as a JS Proxy object.\nThis Proxy records when a state property is accessed or \"used\". Then when that property is mutated,\nthe component is rerendered.\n\nThis means that you can mutate your state in any way, but your component will only rerender if you\nmutate state that you have used.\n\nThe following component will rerender when the button is clicked, because `name` has changed.\n\n```jsx\nimport { useIbiza } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n      <button onClick={() => void (state.name = 'Joel')}></button>\n    </div>\n  )\n}\n```\n\nThe following component will not rerender when the button is clicked, because even though `age` has\nbeen mutated, it is not actually being used within the component.\n\n```jsx\nimport { useIbiza } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n      <button onClick={() => void (state.age = 44)}></button>\n    </div>\n  )\n}\n```\n\nState can be mutated from anywhere - not just from within a component:\n\n```js\nimport { useIbiza, store } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n    </div>\n  )\n}\n\n// <App> component will re-render when this line executes, as `name` has changed.\nstore.state.name = 'Ash'\n```\n\n### Initial State\n\nYou can pass some initial state to `useIbiza` which will be merged with existing state in the Ibiza\nstore.\n\n```jsx\nconst App = () => {\n  const state = useIbiza({ user: { name: 'Joel' } })\n\n  return <h1>Hello {state.user.name}</h1>\n}\n```\n\nThis is safe to include in the body of your component, as it will only be merged into the store on\nfirst render.\n\n### Slicing\n\nIbiza supports deeply nested objects, allowing you to design the shape of your state any way you\nlike. To help you work with such nested state, the `useIbiza` hook supports slicing.\n\nThe following example assumes you have an existing state object:\n\n```javascript\n{\n  user: {\n    name: 'Joel',\n    partner: {\n      name: 'Sam',\n    }\n  }\n}\n```\n\nPass a string to `useIbiza` to fetch a specific slice of state. The string should be the path to the\nobject that you want.\n\n```jsx\nconst App = () => {\n  const partner = useIbiza('user.partner')\n\n  return (\n    <div>\n      <h1>Hello {partner.name}</h1>\n      <button onClick={() => void (partner.name = 'Bob')}></button>\n    </div>\n  )\n}\n```\n\nNote that slicing is really only supported as a convenience, and will not generally help with\nperformance.\n\n## `createModel()`\n\nIbiza is at its most powerful when working with models. They provide reusability and flexibility.\n\nCreate a model using the `createModel` helper, where the first argument is the model name, and the\nsecond argument is the initial model state as a plain object.\n\n```javascript\n// model.js\n\nexport default createModel('user', {\n  firstName: 'Joel',\n  lastName: 'Moss',\n  children: [{ firstName: 'Ash' }, { firstName: 'Elijah' }, { firstName: 'Eve' }]\n})\n```\n\n`createModel` returns a hook which you can use. You can now import your model anywhere:\n\n```jsx\n// app.jsx\n\nimport useModel from './model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <div>\n      <h1>Hello {user.firstName}</h1>\n      <ul>\n        {user.children.map((child, i) => (\n          <li key={i}>{child.firstName}</li>\n        ))}\n      </ul>\n    </div>\n  )\n}\n```\n\n### Initial State\n\nSometimes you want to be able to define your model with some initial state that could be provided\ndynamically. For example, from component props or some other parameters.\n\n`createModel` can accept a function as its second argument. This function will be called on\ninitialisation with two arguments; the current `state` and any `props` passed to it when its hook is\nfirst called.\n\n```javascript\n// model.js\n\nexport default createModel('user', (state, props) => ({\n  firstName: 'Joel',\n  lastName: 'Moss'\n  ...props\n}))\n```\n\n```jsx\n// app.jsx\n\nimport useModel from './model'\n\nconst App = ({ yearOfBirth }) => {\n  const user = useModel({ yearOfBirth })\n\n  return (\n    <div>\n      <h1>\n        Hello {user.firstName}, you were born in {user.yearOfBirth}.\n      </h1>\n    </div>\n  )\n}\n```\n\n### Functions\n\nYou can use regular function in your model. They accept the current state as the first argument, and\n`this` will also be the current state (as long as you don't use hash rocket functions).\n\n```jsx\nconst App = () => {\n  const state = useIbiza({\n    count: 0,\n    increment: state => {\n      ++state.count\n    },\n    decrement() {\n      ++this.count\n    }\n  })\n\n  return (\n    <>\n      <h1>Count = {state.count}</h1>\n      <button onClick={state.increment}>Increment</button>\n      <button onClick={state.decrement}>Decrement</button>\n    </>\n  )\n}\n```\n\nWhen reading/writing state within a function, `this` responds to the state at the level where the\nfunction sits. This means that if the function is deeply nested, `this` will not include state lower\ndown.\n\nTo solve this, you can call `this.$model` to access your model, or `this.$root` to access the root\nof the store state.\n\n```javascript\nuseIbiza({\n  deepstate: {\n    user: {\n      name: 'Joel',\n      partner: {\n        name: 'Sam',\n\n        get partner() {\n          // `this` refers to 'deepstate.user.partner'.\n          // `this.$model` refers to 'deepstate.user'.\n          // `this.$root` is the whole store state.\n          return this.$model.name\n        }\n      }\n    }\n  }\n})\n```\n\nFunctions accept any number of arguments just like regular functions do, but don't forget that the\nfirst argument is always the state.\n\n```jsx\nconst App = () => {\n  const user = useIbiza({\n    children: [],\n    addChild(state, firstName, lastName) {\n      state.children.push({ firstName, lastName }) // or `this.children.push(...)`\n    }\n  })\n\n  return (\n    <>\n      <ul>\n        {user.children.map((child, i) => (\n          <li key={i}>\n            {child.firstName} {child.lastName}\n          </li>\n        ))}\n      </ul>\n      <button onClick={() => user.addChild('Ash', 'Moss')}></button>\n    </>\n  )\n}\n```\n\nNote that used state is not tracked within functions. This avoids unnecessary component re-rendering\nwhen state changes that is used by a function. The function will always use the latest state anyway,\nso no need to track the state that it uses.\n\nThis does however, mean that you should not call functions during rendering - use a getter instead.\n\n### Getters and Setters\n\nIbiza supports Javascript getters and setters in your state and models.\n\n```javascript\nexport default createModel('user', {\n  firstName: 'Joel',\n  lastName: 'Moss',\n\n  get fullName() {\n    // You can read/write to your state via `this`.\n    return `${this.firstName} ${this.lastName}`\n  },\n\n  set fullName(value) {\n    const [firstName, lastName] = value.split(' ')\n\n    this.firstName = firstName\n    this.lastName = lastName\n  }\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <h1>Hello {user.fullName}</h1>\n      <button onClick={() => void (user.fullName = 'Bob Bones')}></button>\n    </>\n  )\n}\n```\n\n### Async Functions\n\nFunctions can be async and/or return Promises, and support React's Suspense by default.\n\n```javascript\nexport default createModel('user', {\n  name: 'Joel',\n\n  async doSomething() {\n    return await someAsyncAction()\n  }\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <h1>Hello {user.fullName}</h1>\n      <button onClick={user.doSomething}></button>\n    </>\n  )\n}\n```\n\n### URL Models\n\nBecause reading and writing to/from the server is so common, Ibiza has support to make this easy\nwith URL Models, similar to react-query. Simply use a valid and relative URL as your model name or\nslice.\n\nThe following will fetch the user from the server at `/user`, suspending the component while it does\nso. The data is fetched only when it does not exist in the store.\n\n```jsx\nconst App = () => {\n  const user = useIbiza('/user')\n\n  return <h1>Hello {user.name}</h1>\n}\n```\n\nYou can safely mutate your model, as all mutations will remain local.\n\nYou can write your model state back to the server. It the server responds with JSON, the model will\nbe updated with that response.\n\n```jsx\nconst App = () => {\n  const user = useIbiza('/user')\n\n  const renameUser = async () => {\n    await user.save({ body: { name: 'Bob' } })\n  }\n\n  return (\n    <>\n      <h1>Hello {user.name}</h1>\n      <button onClick={renameUser}></button>\n    </>\n  )\n}\n```\n\nURL Models can also be defined with `createModel`, and accept the same arguments:\n\n```javascript\nexport default createModel('/user')\n```\n\n`createModel` returns a hook which you can use. You can now import your model anywhere:\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return <h1>Hello {user.firstName}</h1>\n}\n```\n\nAdditionally, URL models accept a `fetcher` option, which when provided, will be used as the fetch\nfunction for the model:\n\n```javascript\nexport default createModel('/user', {}, { fetcher: myFetchFunction })\n```\n\n## `createContextModel()`\n\nWrap your component in the `IbizaProvider` higher order component, and instead of `createModel()`,\ncreate your model with `createContextModel()` function. The model will automatically be given a\nunique name specific to the wrapped components in IbizaProvider. Just pass the model definition as\nthe first argument. It accepts the same options as `createModel()` for the second argument.\n\n```jsx\nconst useModel = createContextModel(() => ({\n  // Your model definition...\n  name: 'Awesome!'\n}))\n\nconst App = () => {\n  return (\n    <IbizaProvider>\n      <MyComponent />\n    </IbizaProvider>\n  );\n};\n\nconst MyComponent = () => {\n  const model = useModel()\n\n  return <h1>My model is {model.name}</h1>\n};\n```\n\nEach instance of IbizaProvider will use its own state.\n\n```jsx\nconst useFirstModel = createContextModel(() => ({\n  name: 'FIRST!'\n}))\n\nconst useSecondModel = createContextModel(() => ({\n  name: 'SECOND!'\n}))\n\nconst App = () => {\n  return (\n    <>\n      <IbizaProvider>\n        <MyFirstComponent />\n      </IbizaProvider>\n      <IbizaProvider>\n        <MySecondComponent />\n      </IbizaProvider>\n    </>\n  );\n};\n\nconst MyFirstComponent = () => {\n  const model = useFirstModel();\n\n  return <h1>My model is {model.name}</h1>; // My model is FIRST!\n};\n\nconst MySecondComponent = () => {\n  const model = useSecondModel()\n\n  return <h1>My model is {model.name}</h1> // My model is SECOND!\n};\n```\n\n## How Does Ibiza Work?\n\nIt's all thanks to the magic of Unicorns! 🦄\n\n...actually, I lie. In reality, the magic is courtesy of [JavaScript Proxies](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy).\n\nAnytime you call `useIbiza` in a component, a Proxy of the store state is returned. Reading\nproperties from this proxy is recorded, and each property is tracked as being used in the component.\nWe call this the Hook Proxy, as it is specific to the instance of the `useIbiza` hook, and therefore\nthe component it is used within.\n\nYou can read and write from/to the Hook Proxy, as you would any JavaScript object. Reading, or using\na property, will cause the component to re-render when the property's value is mutated. And mutating\na property value will cause any component that has read the same property, to re-render.\n\nThe Hook Proxy wraps the Store Proxy, which contains the actual Ibiza global state. As with the Hook\nProxy, the Store Proxy can be read and written to, and components that have used the state will\nre-render upon mutation. This means you can mutate the state via the Hook Proxy and/or the Store\nProxy. The Store Proxy does not track property usage.\n","readmeFilename":"README.md","_id":"ibiza@2.0.0-alpha.11","_integrity":"sha512-m0X9D+hoOrTt6ZtcHL8KCxTyTY8dLY25QseZ4SEVC22nqO/IYL1RnMT18CGdMY7iH6vLuTzxd0779mb3RsZENA==","_resolved":"/private/var/folders/3b/b6pthvr51cg1755k2jxx8www0000gn/T/afc56608d297ad0df2f4898ab2476dc1/ibiza-2.0.0-alpha.11.tgz","_from":"file:ibiza-2.0.0-alpha.11.tgz","_nodeVersion":"18.9.0","_npmVersion":"8.19.1","dist":{"integrity":"sha512-m0X9D+hoOrTt6ZtcHL8KCxTyTY8dLY25QseZ4SEVC22nqO/IYL1RnMT18CGdMY7iH6vLuTzxd0779mb3RsZENA==","shasum":"f2b5cfbe4e3d2e0a0e9a84d68ddd70f292ed6fa4","tarball":"https://registry.npmjs.org/ibiza/-/ibiza-2.0.0-alpha.11.tgz","fileCount":10,"unpackedSize":338174,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCfE63h191pJ/aJF9uhjyhOfVZNCzUErJTTbk5LAOAaSAIgQblM+AIGbSBBg4hlcqYl4Y8vdgM+S/tIKNHTtm20Ecc="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjNBSDACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmp5lQ//VKrNrd3X3lkeZF9D3y1HwJZnnNXfnkilG43qmlrRU5T3RXxN\r\nbae4lkh1YyTe6rCbXmnWTQp4uQbljv+cnLu7nfxUIByxe8drXsZa/9FxgKzI\r\n5TcP8FmoKpvenv6e7iQgdrnYep3IAAAXWQxQBMNj6Ngkap/bCVpwyWdMA+qR\r\nqPIMEMwHpeH/7cxvU8vsPsHMJX7BbBKRBM7R8lpLMw6xo8BrjytTlT1T/nSX\r\n4l+IqT8u/6EFaAkb//MoG79ZEPoJRLcGXjbSHPF01zLLMG92L7O1SNAK0SVY\r\nJ3uw7H3mAtlAJj8tYHLkfRbyLrksk3P+027YSm/mYlrdMCHNQA+FhIRZWLQJ\r\n58eea3iD7v3vrlz062DZxgqU2VAecgESz+1DF2lllnBtaiYTNbuXOkssBRw+\r\nbPRg49tcUgRH2terzZTrA9sZ23GxzCx5mAe7yryljj3Xg2cvrUKlUzU08ZQg\r\nSWaNWEp+yHO72eWe3hM5TdDBTJkD007ni9FohM0iWhvtYFrFkmpIOyXH8UvL\r\nPxukC+BEuWd0X7GjVlH91BJBT1YoctOG2AZWeEgm2f6u5OhU5JZmDWcDfjg/\r\nYkgjEVx3Vzs5AReDQnL6i9FZMLUHWNh+gAHtsYFUYjSLD0n3x4mxSs9rOAy3\r\nqfPiuzPE5PJdq1fZtcmDdcpFXxGxDk0suCY=\r\n=yJys\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"joelmoss","email":"joel@developwithstyle.com"},"directories":{},"maintainers":[{"name":"joelmoss","email":"joel@developwithstyle.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ibiza_2.0.0-alpha.11_1664357507077_0.6667483385887532"},"_hasShrinkwrap":false},"2.0.0-alpha.12":{"name":"ibiza","author":{"name":"Joel Moss"},"version":"2.0.0-alpha.12","description":"React State Management for Party Animals","license":"MIT","homepage":"https://github.com/joelmoss/ibiza","repository":{"type":"git","url":"git+https://github.com/joelmoss/ibiza.git"},"bugs":{"url":"https://github.com/joelmoss/ibiza/issues"},"keywords":["react","state","proxy"],"type":"module","source":"src/index.js","main":"dist/ibiza.cjs","module":"dist/ibiza.module.js","unpkg":"dist/ibiza.umd.js","exports":{"require":"./dist/ibiza.cjs","default":"./dist/ibiza.modern.js"},"sideEffects":false,"eslintConfig":{"extends":["eslint:recommended","plugin:react/recommended","plugin:react-hooks/recommended","plugin:prettier/recommended"],"settings":{"react":{"version":"detect"}},"env":{"browser":true,"node":false,"es6":true},"parserOptions":{"ecmaVersion":"latest","sourceType":"module","ecmaFeatures":{"jsx":true}},"rules":{"react/prop-types":0},"overrides":[{"files":["test/**"],"extends":["plugin:jest/recommended","plugin:testing-library/react","plugin:jest/style"],"rules":{"jest/expect-expect":["warn",{"assertFunctionNames":["expect","screen.findByText","screen.getByText"]}]}}]},"size-limit":[{"name":"useIbiza","path":"./src/index.js","import":"{ useIbiza }","limit":"1 s"},{"name":"store","path":"./src/index.js","import":"{ store }","limit":"1 s"},{"name":"createModel","path":"./src/index.js","import":"{ createModel }","limit":"1 s"},{"name":"unproxiedStateOf","path":"./src/index.js","import":"{ unproxiedStateOf }","limit":"1 s"},{"name":"freeze","path":"./src/index.js","import":"{ freeze }","limit":"1 s"}],"prettier":{"trailingComma":"none","printWidth":100,"semi":false,"singleQuote":true,"arrowParens":"avoid"},"peerDependencies":{"react":">=17"},"devDependencies":{"@size-limit/preset-big-lib":"^8.1","@swc/core":"^1.2.144","@swc/jest":"^0.2.17","@testing-library/dom":"^8.14.0","@testing-library/jest-dom":"^5.15.0","@testing-library/react":"^13.0.0","@testing-library/user-event":"^14.2.1","cross-fetch":"^3.1.4","eslint":"^8.18.0","eslint-config-prettier":"^8.5.0","eslint-plugin-jest":"^27.0","eslint-plugin-prettier":"^4.0.0","eslint-plugin-react":"^7.30.0","eslint-plugin-react-hooks":"^4.6.0","eslint-plugin-testing-library":"^5.5.1","fetch-mock-jest":"^1.5.1","ibiza":"link:./ibiza","jest":"^29.1","jest-environment-jsdom":"^29.1.0","microbundle":"^0.15.0","msw":"^0.47","prettier":"^2.7.1","react":"^18.2.0","react-dom":"^18.2.0","react-error-boundary":"^3.1.4","rimraf":"^3.0.2","size-limit":"^8.1.0"},"dependencies":{"fast-equals":"^4.0.0","micro-memoize":"^4.0.9"},"scripts":{"clean":"rimraf dist","test":"jest","build":"microbundle --jsx React.createElement","dev":"microbundle watch --jsx React.createElement --compress false","size":"microbundle && size-limit","lint":"eslint src test --ext .jsx --ext .js"},"readme":"# Ibiza - React State Management for Party Animals\n\nIbiza gets out of your way and simply lets you read and write state as you would with regular\nJavascript assignment. It maintains a global state object and is smart enough to know when to\nrerender your components based on state usage and modification.\n\n## `useIbiza()` ✨\n\nA component calls the `useIbiza` React hook, which returns the store state as a JS Proxy object.\nThis Proxy records when a state property is accessed or \"used\". Then when that property is mutated,\nthe component is rerendered.\n\nThis means that you can mutate your state in any way, but your component will only rerender if you\nmutate state that you have used.\n\nThe following component will rerender when the button is clicked, because `name` has changed.\n\n```jsx\nimport { useIbiza } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n      <button onClick={() => void (state.name = 'Joel')}></button>\n    </div>\n  )\n}\n```\n\nThe following component will not rerender when the button is clicked, because even though `age` has\nbeen mutated, it is not actually being used within the component.\n\n```jsx\nimport { useIbiza } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n      <button onClick={() => void (state.age = 44)}></button>\n    </div>\n  )\n}\n```\n\nState can be mutated from anywhere - not just from within a component:\n\n```js\nimport { useIbiza, store } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n    </div>\n  )\n}\n\n// <App> component will re-render when this line executes, as `name` has changed.\nstore.state.name = 'Ash'\n```\n\n### Initial State\n\nYou can pass some initial state to `useIbiza` which will be merged with existing state in the Ibiza\nstore.\n\n```jsx\nconst App = () => {\n  const state = useIbiza({ user: { name: 'Joel' } })\n\n  return <h1>Hello {state.user.name}</h1>\n}\n```\n\nThis is safe to include in the body of your component, as it will only be merged into the store on\nfirst render.\n\n### Slicing\n\nIbiza supports deeply nested objects, allowing you to design the shape of your state any way you\nlike. To help you work with such nested state, the `useIbiza` hook supports slicing.\n\nThe following example assumes you have an existing state object:\n\n```javascript\n{\n  user: {\n    name: 'Joel',\n    partner: {\n      name: 'Sam',\n    }\n  }\n}\n```\n\nPass a string to `useIbiza` to fetch a specific slice of state. The string should be the path to the\nobject that you want.\n\n```jsx\nconst App = () => {\n  const partner = useIbiza('user.partner')\n\n  return (\n    <div>\n      <h1>Hello {partner.name}</h1>\n      <button onClick={() => void (partner.name = 'Bob')}></button>\n    </div>\n  )\n}\n```\n\nNote that slicing is really only supported as a convenience, and will not generally help with\nperformance.\n\n## `createModel()`\n\nIbiza is at its most powerful when working with models. They provide reusability and flexibility.\n\nCreate a model using the `createModel` helper, where the first argument is the model name, and the\nsecond argument is the initial model state as a plain object.\n\n```javascript\n// model.js\n\nexport default createModel('user', {\n  firstName: 'Joel',\n  lastName: 'Moss',\n  children: [{ firstName: 'Ash' }, { firstName: 'Elijah' }, { firstName: 'Eve' }]\n})\n```\n\n`createModel` returns a hook which you can use. You can now import your model anywhere:\n\n```jsx\n// app.jsx\n\nimport useModel from './model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <div>\n      <h1>Hello {user.firstName}</h1>\n      <ul>\n        {user.children.map((child, i) => (\n          <li key={i}>{child.firstName}</li>\n        ))}\n      </ul>\n    </div>\n  )\n}\n```\n\n### Initial State\n\nSometimes you want to be able to define your model with some initial state that could be provided\ndynamically. For example, from component props or some other parameters.\n\n`createModel` can accept a function as its second argument. This function will be called on\ninitialisation with two arguments; the current `state` and any `props` passed to it when its hook is\nfirst called.\n\n```javascript\n// model.js\n\nexport default createModel('user', (state, props) => ({\n  firstName: 'Joel',\n  lastName: 'Moss'\n  ...props\n}))\n```\n\n```jsx\n// app.jsx\n\nimport useModel from './model'\n\nconst App = ({ yearOfBirth }) => {\n  const user = useModel({ yearOfBirth })\n\n  return (\n    <div>\n      <h1>\n        Hello {user.firstName}, you were born in {user.yearOfBirth}.\n      </h1>\n    </div>\n  )\n}\n```\n\n### Functions\n\nYou can use regular function in your model. They accept the current state as the first argument, and\n`this` will also be the current state (as long as you don't use hash rocket functions).\n\n```jsx\nconst App = () => {\n  const state = useIbiza({\n    count: 0,\n    increment: state => {\n      ++state.count\n    },\n    decrement() {\n      ++this.count\n    }\n  })\n\n  return (\n    <>\n      <h1>Count = {state.count}</h1>\n      <button onClick={state.increment}>Increment</button>\n      <button onClick={state.decrement}>Decrement</button>\n    </>\n  )\n}\n```\n\nWhen reading/writing state within a function, `this` responds to the state at the level where the\nfunction sits. This means that if the function is deeply nested, `this` will not include state lower\ndown.\n\nTo solve this, you can call `this.$model` to access your model, or `this.$root` to access the root\nof the store state.\n\n```javascript\nuseIbiza({\n  deepstate: {\n    user: {\n      name: 'Joel',\n      partner: {\n        name: 'Sam',\n\n        get partner() {\n          // `this` refers to 'deepstate.user.partner'.\n          // `this.$model` refers to 'deepstate.user'.\n          // `this.$root` is the whole store state.\n          return this.$model.name\n        }\n      }\n    }\n  }\n})\n```\n\nFunctions accept any number of arguments just like regular functions do, but don't forget that the\nfirst argument is always the state.\n\n```jsx\nconst App = () => {\n  const user = useIbiza({\n    children: [],\n    addChild(state, firstName, lastName) {\n      state.children.push({ firstName, lastName }) // or `this.children.push(...)`\n    }\n  })\n\n  return (\n    <>\n      <ul>\n        {user.children.map((child, i) => (\n          <li key={i}>\n            {child.firstName} {child.lastName}\n          </li>\n        ))}\n      </ul>\n      <button onClick={() => user.addChild('Ash', 'Moss')}></button>\n    </>\n  )\n}\n```\n\nNote that used state is not tracked within functions. This avoids unnecessary component re-rendering\nwhen state changes that is used by a function. The function will always use the latest state anyway,\nso no need to track the state that it uses.\n\nThis does however, mean that you should not call functions during rendering - use a getter instead.\n\n### Getters and Setters\n\nIbiza supports Javascript getters and setters in your state and models.\n\n```javascript\nexport default createModel('user', {\n  firstName: 'Joel',\n  lastName: 'Moss',\n\n  get fullName() {\n    // You can read/write to your state via `this`.\n    return `${this.firstName} ${this.lastName}`\n  },\n\n  set fullName(value) {\n    const [firstName, lastName] = value.split(' ')\n\n    this.firstName = firstName\n    this.lastName = lastName\n  }\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <h1>Hello {user.fullName}</h1>\n      <button onClick={() => void (user.fullName = 'Bob Bones')}></button>\n    </>\n  )\n}\n```\n\n### Async Functions\n\nFunctions can be async and/or return Promises, and support React's Suspense by default.\n\n```javascript\nexport default createModel('user', {\n  name: 'Joel',\n\n  async doSomething() {\n    return await someAsyncAction()\n  }\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <h1>Hello {user.fullName}</h1>\n      <button onClick={user.doSomething}></button>\n    </>\n  )\n}\n```\n\n### URL Models\n\nBecause reading and writing to/from the server is so common, Ibiza has support to make this easy\nwith URL Models, similar to react-query. Simply use a valid and relative URL as your model name or\nslice.\n\nThe following will fetch the user from the server at `/user`, suspending the component while it does\nso. The data is fetched only when it does not exist in the store.\n\n```jsx\nconst App = () => {\n  const user = useIbiza('/user')\n\n  return <h1>Hello {user.name}</h1>\n}\n```\n\nYou can safely mutate your model, as all mutations will remain local.\n\nYou can write your model state back to the server. It the server responds with JSON, the model will\nbe updated with that response.\n\n```jsx\nconst App = () => {\n  const user = useIbiza('/user')\n\n  const renameUser = async () => {\n    await user.save({ body: { name: 'Bob' } })\n  }\n\n  return (\n    <>\n      <h1>Hello {user.name}</h1>\n      <button onClick={renameUser}></button>\n    </>\n  )\n}\n```\n\nURL Models can also be defined with `createModel`, and accept the same arguments:\n\n```javascript\nexport default createModel('/user')\n```\n\n`createModel` returns a hook which you can use. You can now import your model anywhere:\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return <h1>Hello {user.firstName}</h1>\n}\n```\n\nAdditionally, URL models accept a `fetcher` option, which when provided, will be used as the fetch\nfunction for the model:\n\n```javascript\nexport default createModel('/user', {}, { fetcher: myFetchFunction })\n```\n\n## `createContextModel()`\n\nWrap your component in the `IbizaProvider` higher order component, and instead of `createModel()`,\ncreate your model with `createContextModel()` function. The model will automatically be given a\nunique name specific to the wrapped components in IbizaProvider. Just pass the model definition as\nthe first argument. It accepts the same options as `createModel()` for the second argument.\n\n```jsx\nconst useModel = createContextModel(() => ({\n  // Your model definition...\n  name: 'Awesome!'\n}))\n\nconst App = () => {\n  return (\n    <IbizaProvider>\n      <MyComponent />\n    </IbizaProvider>\n  );\n};\n\nconst MyComponent = () => {\n  const model = useModel()\n\n  return <h1>My model is {model.name}</h1>\n};\n```\n\nEach instance of IbizaProvider will use its own state.\n\n```jsx\nconst useFirstModel = createContextModel(() => ({\n  name: 'FIRST!'\n}))\n\nconst useSecondModel = createContextModel(() => ({\n  name: 'SECOND!'\n}))\n\nconst App = () => {\n  return (\n    <>\n      <IbizaProvider>\n        <MyFirstComponent />\n      </IbizaProvider>\n      <IbizaProvider>\n        <MySecondComponent />\n      </IbizaProvider>\n    </>\n  );\n};\n\nconst MyFirstComponent = () => {\n  const model = useFirstModel();\n\n  return <h1>My model is {model.name}</h1>; // My model is FIRST!\n};\n\nconst MySecondComponent = () => {\n  const model = useSecondModel()\n\n  return <h1>My model is {model.name}</h1> // My model is SECOND!\n};\n```\n\n## How Does Ibiza Work?\n\nIt's all thanks to the magic of Unicorns! 🦄\n\n...actually, I lie. In reality, the magic is courtesy of [JavaScript Proxies](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy).\n\nAnytime you call `useIbiza` in a component, a Proxy of the store state is returned. Reading\nproperties from this proxy is recorded, and each property is tracked as being used in the component.\nWe call this the Hook Proxy, as it is specific to the instance of the `useIbiza` hook, and therefore\nthe component it is used within.\n\nYou can read and write from/to the Hook Proxy, as you would any JavaScript object. Reading, or using\na property, will cause the component to re-render when the property's value is mutated. And mutating\na property value will cause any component that has read the same property, to re-render.\n\nThe Hook Proxy wraps the Store Proxy, which contains the actual Ibiza global state. As with the Hook\nProxy, the Store Proxy can be read and written to, and components that have used the state will\nre-render upon mutation. This means you can mutate the state via the Hook Proxy and/or the Store\nProxy. The Store Proxy does not track property usage.\n","readmeFilename":"README.md","_id":"ibiza@2.0.0-alpha.12","_integrity":"sha512-JzF35LIlf4SNem5dEdkhhzGXuXNP9Y8t7ASY7idYaB/drfoRbFHKnZXTOk1EGOC0Rq654/7ZK0vUh/LgLnaFog==","_resolved":"/private/var/folders/3b/b6pthvr51cg1755k2jxx8www0000gn/T/f711cc4789249c12fe63fb33a1ce3c28/ibiza-2.0.0-alpha.12.tgz","_from":"file:ibiza-2.0.0-alpha.12.tgz","_nodeVersion":"19.0.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-JzF35LIlf4SNem5dEdkhhzGXuXNP9Y8t7ASY7idYaB/drfoRbFHKnZXTOk1EGOC0Rq654/7ZK0vUh/LgLnaFog==","shasum":"97729b41766d5694a19c903c896128d2dbc9093f","tarball":"https://registry.npmjs.org/ibiza/-/ibiza-2.0.0-alpha.12.tgz","fileCount":10,"unpackedSize":336359,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIG8cz9k6orNgiKPNxx5bS8ulcQXC03OiujRlQ/rwZ1jaAiA8MFj4XkuO402QScPJc/lb3wzlgPVrN8l4Nzy0UcccLQ=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjdT8EACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpbWA/9GjrxhHwfVhcaAmuWKp6giZoS9noFw/A092aazCI4MgB9lmNI\r\nItqws+jhpN3NvrisyXqCH3Mm46jQ8dG+L9eSqvwMHqTzLmO4Co1anBaOrAhR\r\nlrDJsg7HiF2uEBDeluqqWZhtIjFeKPRWTzpgtlC8fa19SQnAQg4FdTAAX+Db\r\n0rHEc76gdDEweDFT+9NcAKoDVnZ2R4cy6oB2EL+qfQjYiJE+4KcYH3DvUM+y\r\nmIDfRjNbZ+441/S7Wm8LB50YRFZMS1RcMWN9XUG1gbg57DMQ103bk+Mphr0V\r\n7sT5/I+2wFHb8SSv3G0t6/9JVZPgBd29bTXNa4YDZMmt42IWMKzk36V32KAZ\r\nYcm/vCw+uNVe3Tpds47lmfSPhMCqw8dy0nKDWEjzl2gyFjuFVkHE6MnPxrq8\r\nRms+cbAEOQLAGYz/1iUxXCVaxNhSkUtaks8nitfIuW+HLAY5cttlYeEKrL2k\r\nz7aEKIBeQ1B+bzh79EW5T5shrqNBB3hBxBcGmr67zRwBGRWqD/Ejs+1Oklzj\r\nab7H6+k7xnEuOmfdfAXEuoddObMuoM9F3/AKnfriEHA6EKBdq75as3ZgEld3\r\nVq5qNURwA1x+kbbWezZtuGH+JKC7aihnfVpMCC6pgOQSn122d3ZIVfqImgvB\r\nbSNuwG5AKmtkE2Vr8szX7xisB0Va5Lsp9Gw=\r\n=prbk\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"joelmoss","email":"joel@developwithstyle.com"},"directories":{},"maintainers":[{"name":"joelmoss","email":"joel@developwithstyle.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ibiza_2.0.0-alpha.12_1668628227963_0.5463752686654788"},"_hasShrinkwrap":false},"2.0.0-alpha.13":{"name":"ibiza","author":{"name":"Joel Moss"},"version":"2.0.0-alpha.13","description":"React State Management for Party Animals","license":"MIT","homepage":"https://github.com/joelmoss/ibiza","repository":{"type":"git","url":"git+https://github.com/joelmoss/ibiza.git"},"bugs":{"url":"https://github.com/joelmoss/ibiza/issues"},"keywords":["react","state","proxy"],"packageManager":"pnpm@8.2.0","type":"module","source":"src/index.js","main":"dist/ibiza.cjs","module":"dist/ibiza.module.js","unpkg":"dist/ibiza.umd.js","exports":{"require":"./dist/ibiza.cjs","default":"./dist/ibiza.modern.js"},"sideEffects":false,"eslintConfig":{"extends":["eslint:recommended","plugin:react/recommended","plugin:react-hooks/recommended","plugin:prettier/recommended"],"settings":{"react":{"version":"detect"}},"env":{"browser":true,"node":false,"es6":true},"parserOptions":{"ecmaVersion":"latest","sourceType":"module","ecmaFeatures":{"jsx":true}},"rules":{"react/prop-types":0},"overrides":[{"files":["test/**"],"extends":["plugin:jest/recommended","plugin:testing-library/react","plugin:jest/style"],"rules":{"jest/expect-expect":["warn",{"assertFunctionNames":["expect","screen.findByText","screen.getByText"]}]}}]},"size-limit":[{"name":"useIbiza","path":"./src/index.js","import":"{ useIbiza }","limit":"1 s"},{"name":"store","path":"./src/index.js","import":"{ store }","limit":"1 s"},{"name":"createModel","path":"./src/index.js","import":"{ createModel }","limit":"1 s"},{"name":"unproxiedStateOf","path":"./src/index.js","import":"{ unproxiedStateOf }","limit":"1 s"},{"name":"freeze","path":"./src/index.js","import":"{ freeze }","limit":"1 s"}],"prettier":{"trailingComma":"none","printWidth":100,"semi":false,"singleQuote":true,"arrowParens":"avoid"},"peerDependencies":{"react":">=18"},"devDependencies":{"@size-limit/preset-big-lib":"^8.2.4","@swc/core":"^1.3.49","@swc/jest":"^0.2.24","@testing-library/dom":"^9.2.0","@testing-library/jest-dom":"^5.16.5","@testing-library/react":"^14.0.0","@testing-library/user-event":"^14.4.3","cross-fetch":"^3.1.5","eslint":"^8.38.0","eslint-config-prettier":"^8.8.0","eslint-plugin-jest":"^27.2.1","eslint-plugin-prettier":"^4.2.1","eslint-plugin-react":"^7.32.2","eslint-plugin-react-hooks":"^4.6.0","eslint-plugin-testing-library":"^5.10.3","fetch-mock-jest":"^1.5.1","ibiza":"link:ibiza","jest":"^29.5.0","jest-environment-jsdom":"^29.5.0","microbundle":"^0.15.1","msw":"^1.2.1","prettier":"^2.8.7","react":"^18.2.0","react-dom":"^18.2.0","react-error-boundary":"^4.0.3","rimraf":"^5.0.0","size-limit":"^8.2.4"},"dependencies":{"fast-equals":"^5.0.1","micro-memoize":"^4.0.14"},"scripts":{"clean":"rimraf dist","test":"jest","build":"microbundle --jsx React.createElement","dev":"microbundle watch --jsx React.createElement --compress false","size":"microbundle && size-limit","lint":"eslint src test --ext .jsx --ext .js"},"readme":"# Ibiza - React State Management for Party Animals\n\nIbiza gets out of your way and simply lets you read and write state as you would with regular\nJavascript assignment. It maintains a global state object and is smart enough to know when to\nrerender your components based on state usage and modification.\n\n## `useIbiza()` ✨\n\nA component calls the `useIbiza` React hook, which returns the store state as a JS Proxy object.\nThis Proxy records when a state property is accessed or \"used\". Then when that property is mutated,\nthe component is rerendered.\n\nThis means that you can mutate your state in any way, but your component will only rerender if you\nmutate state that you have used.\n\nThe following component will rerender when the button is clicked, because `name` has changed.\n\n```jsx\nimport { useIbiza } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n      <button onClick={() => void (state.name = 'Joel')}></button>\n    </div>\n  )\n}\n```\n\nThe following component will not rerender when the button is clicked, because even though `age` has\nbeen mutated, it is not actually being used within the component.\n\n```jsx\nimport { useIbiza } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n      <button onClick={() => void (state.age = 44)}></button>\n    </div>\n  )\n}\n```\n\nState can be mutated from anywhere - not just from within a component:\n\n```js\nimport { useIbiza, store } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n    </div>\n  )\n}\n\n// <App> component will re-render when this line executes, as `name` has changed.\nstore.state.name = 'Ash'\n```\n\n### Initial State\n\nYou can pass some initial state to `useIbiza` which will be merged with existing state in the Ibiza\nstore.\n\n```jsx\nconst App = () => {\n  const state = useIbiza({ user: { name: 'Joel' } })\n\n  return <h1>Hello {state.user.name}</h1>\n}\n```\n\nThis is safe to include in the body of your component, as it will only be merged into the store on\nfirst render.\n\n### Slicing\n\nIbiza supports deeply nested objects, allowing you to design the shape of your state any way you\nlike. To help you work with such nested state, the `useIbiza` hook supports slicing.\n\nThe following example assumes you have an existing state object:\n\n```javascript\n{\n  user: {\n    name: 'Joel',\n    partner: {\n      name: 'Sam',\n    }\n  }\n}\n```\n\nPass a string to `useIbiza` to fetch a specific slice of state. The string should be the path to the\nobject that you want.\n\n```jsx\nconst App = () => {\n  const partner = useIbiza('user.partner')\n\n  return (\n    <div>\n      <h1>Hello {partner.name}</h1>\n      <button onClick={() => void (partner.name = 'Bob')}></button>\n    </div>\n  )\n}\n```\n\nNote that slicing is really only supported as a convenience, and will not generally help with\nperformance.\n\n## `createModel()`\n\nIbiza is at its most powerful when working with models. They provide reusability and flexibility.\n\nCreate a model using the `createModel` helper, where the first argument is the model name, and the\nsecond argument is the initial model state as a plain object.\n\n```javascript\n// model.js\n\nexport default createModel('user', {\n  firstName: 'Joel',\n  lastName: 'Moss',\n  children: [{ firstName: 'Ash' }, { firstName: 'Elijah' }, { firstName: 'Eve' }]\n})\n```\n\n`createModel` returns a hook which you can use. You can now import your model anywhere:\n\n```jsx\n// app.jsx\n\nimport useModel from './model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <div>\n      <h1>Hello {user.firstName}</h1>\n      <ul>\n        {user.children.map((child, i) => (\n          <li key={i}>{child.firstName}</li>\n        ))}\n      </ul>\n    </div>\n  )\n}\n```\n\n### Initial State\n\nSometimes you want to be able to define your model with some initial state that could be provided\ndynamically. For example, from component props or some other parameters.\n\n`createModel` can accept a function as its second argument. This function will be called on\ninitialisation with two arguments; the current `state` and any `props` passed to it when its hook is\nfirst called.\n\n```javascript\n// model.js\n\nexport default createModel('user', (state, props) => ({\n  firstName: 'Joel',\n  lastName: 'Moss'\n  ...props\n}))\n```\n\n```jsx\n// app.jsx\n\nimport useModel from './model'\n\nconst App = ({ yearOfBirth }) => {\n  const user = useModel({ yearOfBirth })\n\n  return (\n    <div>\n      <h1>\n        Hello {user.firstName}, you were born in {user.yearOfBirth}.\n      </h1>\n    </div>\n  )\n}\n```\n\n### Functions\n\nYou can use regular function in your model. They accept the current state as the first argument, and\n`this` will also be the current state (as long as you don't use hash rocket functions).\n\n```jsx\nconst App = () => {\n  const state = useIbiza({\n    count: 0,\n    increment: state => {\n      ++state.count\n    },\n    decrement() {\n      ++this.count\n    }\n  })\n\n  return (\n    <>\n      <h1>Count = {state.count}</h1>\n      <button onClick={state.increment}>Increment</button>\n      <button onClick={state.decrement}>Decrement</button>\n    </>\n  )\n}\n```\n\nWhen reading/writing state within a function, `this` responds to the state at the level where the\nfunction sits. This means that if the function is deeply nested, `this` will not include state lower\ndown.\n\nTo solve this, you can call `this.$model` to access your model, or `this.$root` to access the root\nof the store state.\n\n```javascript\nuseIbiza({\n  deepstate: {\n    user: {\n      name: 'Joel',\n      partner: {\n        name: 'Sam',\n\n        get partner() {\n          // `this` refers to 'deepstate.user.partner'.\n          // `this.$model` refers to 'deepstate.user'.\n          // `this.$root` is the whole store state.\n          return this.$model.name\n        }\n      }\n    }\n  }\n})\n```\n\nFunctions accept any number of arguments just like regular functions do, but don't forget that the\nfirst argument is always the state.\n\n```jsx\nconst App = () => {\n  const user = useIbiza({\n    children: [],\n    addChild(state, firstName, lastName) {\n      state.children.push({ firstName, lastName }) // or `this.children.push(...)`\n    }\n  })\n\n  return (\n    <>\n      <ul>\n        {user.children.map((child, i) => (\n          <li key={i}>\n            {child.firstName} {child.lastName}\n          </li>\n        ))}\n      </ul>\n      <button onClick={() => user.addChild('Ash', 'Moss')}></button>\n    </>\n  )\n}\n```\n\nNote that used state is not tracked within functions. This avoids unnecessary component re-rendering\nwhen state changes that is used by a function. The function will always use the latest state anyway,\nso no need to track the state that it uses.\n\nThis does however, mean that you should not call functions during rendering - use a getter instead.\n\n### Getters and Setters\n\nIbiza supports Javascript getters and setters in your state and models.\n\n```javascript\nexport default createModel('user', {\n  firstName: 'Joel',\n  lastName: 'Moss',\n\n  get fullName() {\n    // You can read/write to your state via `this`.\n    return `${this.firstName} ${this.lastName}`\n  },\n\n  set fullName(value) {\n    const [firstName, lastName] = value.split(' ')\n\n    this.firstName = firstName\n    this.lastName = lastName\n  }\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <h1>Hello {user.fullName}</h1>\n      <button onClick={() => void (user.fullName = 'Bob Bones')}></button>\n    </>\n  )\n}\n```\n\n### Async Functions\n\nFunctions can be async and/or return Promises, and support React's Suspense by default.\n\n```javascript\nexport default createModel('user', {\n  name: 'Joel',\n\n  async doSomething() {\n    return await someAsyncAction()\n  }\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <h1>Hello {user.fullName}</h1>\n      <button onClick={user.doSomething}></button>\n    </>\n  )\n}\n```\n\n### URL Models\n\nBecause reading and writing to/from the server is so common, Ibiza has support to make this easy\nwith URL Models, similar to react-query. Simply use a valid and relative URL as your model name or\nslice.\n\nThe following will fetch the user from the server at `/user`, suspending the component while it does\nso. The data is fetched only when it does not exist in the store.\n\n```jsx\nconst App = () => {\n  const user = useIbiza('/user')\n\n  return <h1>Hello {user.name}</h1>\n}\n```\n\nYou can safely mutate your model, as all mutations will remain local.\n\nYou can write your model state back to the server using `$save()`. It the server responds with JSON,\nthe model will be updated with that response.\n\n```jsx\nconst App = () => {\n  const user = useIbiza('/user')\n\n  const renameUser = async () => {\n    await user.$save({ body: { name: 'Bob' } })\n  }\n\n  return (\n    <>\n      <h1>Hello {user.name}</h1>\n      <button onClick={renameUser}></button>\n    </>\n  )\n}\n```\n\nURL Models can also be defined with `createModel`, and accept the same arguments:\n\n```javascript\nexport default createModel('/user')\n```\n\n`createModel` returns a hook which you can use. You can now import your model anywhere:\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return <h1>Hello {user.firstName}</h1>\n}\n```\n\nAdditionally, URL models accept a `fetcher` option, which when provided, will be used as the fetch\nfunction for the model:\n\n```javascript\nexport default createModel('/user', {}, { fetcher: myFetchFunction })\n```\n\n## `createContextModel()`\n\nWrap your component in the `IbizaProvider` higher order component, and instead of `createModel()`,\ncreate your model with `createContextModel()` function. The model will automatically be given a\nunique name specific to the wrapped components in IbizaProvider. Just pass the model definition as\nthe first argument. It accepts the same options as `createModel()` for the second argument.\n\n```jsx\nconst useModel = createContextModel(() => ({\n  // Your model definition...\n  name: 'Awesome!'\n}))\n\nconst App = () => {\n  return (\n    <IbizaProvider>\n      <MyComponent />\n    </IbizaProvider>\n  );\n};\n\nconst MyComponent = () => {\n  const model = useModel()\n\n  return <h1>My model is {model.name}</h1>\n};\n```\n\nEach instance of IbizaProvider will use its own state.\n\n```jsx\nconst useFirstModel = createContextModel(() => ({\n  name: 'FIRST!'\n}))\n\nconst useSecondModel = createContextModel(() => ({\n  name: 'SECOND!'\n}))\n\nconst App = () => {\n  return (\n    <>\n      <IbizaProvider>\n        <MyFirstComponent />\n      </IbizaProvider>\n      <IbizaProvider>\n        <MySecondComponent />\n      </IbizaProvider>\n    </>\n  );\n};\n\nconst MyFirstComponent = () => {\n  const model = useFirstModel();\n\n  return <h1>My model is {model.name}</h1>; // My model is FIRST!\n};\n\nconst MySecondComponent = () => {\n  const model = useSecondModel()\n\n  return <h1>My model is {model.name}</h1> // My model is SECOND!\n};\n```\n\n## How Does Ibiza Work?\n\nIt's all thanks to the magic of Unicorns! 🦄\n\n...actually, I lie. In reality, the magic is courtesy of [JavaScript Proxies](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy).\n\nAnytime you call `useIbiza` in a component, a Proxy of the store state is returned. Reading\nproperties from this proxy is recorded, and each property is tracked as being used in the component.\nWe call this the Hook Proxy, as it is specific to the instance of the `useIbiza` hook, and therefore\nthe component it is used within.\n\nYou can read and write from/to the Hook Proxy, as you would any JavaScript object. Reading, or using\na property, will cause the component to re-render when the property's value is mutated. And mutating\na property value will cause any component that has read the same property, to re-render.\n\nThe Hook Proxy wraps the Store Proxy, which contains the actual Ibiza global state. As with the Hook\nProxy, the Store Proxy can be read and written to, and components that have used the state will\nre-render upon mutation. This means you can mutate the state via the Hook Proxy and/or the Store\nProxy. The Store Proxy does not track property usage.\n","readmeFilename":"README.md","_id":"ibiza@2.0.0-alpha.13","_integrity":"sha512-HCO5IlqgAD51CdYT3g51dIoShggRCUulD7yFLnGJ3TMTYGdKBc09yJnYyY70YuqSyuTUGE+Jda2g7CIEAYoxeg==","_resolved":"/private/var/folders/3b/b6pthvr51cg1755k2jxx8www0000gn/T/51f66ad72fe7eadcecabca4fde941a75/ibiza-2.0.0-alpha.13.tgz","_from":"file:ibiza-2.0.0-alpha.13.tgz","_nodeVersion":"19.8.1","_npmVersion":"9.5.1","dist":{"integrity":"sha512-HCO5IlqgAD51CdYT3g51dIoShggRCUulD7yFLnGJ3TMTYGdKBc09yJnYyY70YuqSyuTUGE+Jda2g7CIEAYoxeg==","shasum":"3b5cd6c454aa4738d5d8ea3a7834ba28740a33f6","tarball":"https://registry.npmjs.org/ibiza/-/ibiza-2.0.0-alpha.13.tgz","fileCount":10,"unpackedSize":339559,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGhiTeS9JYBD6NZc3jkP4HCWOilQ+i8qhqphyukuyAIHAiB65crS/Ie18//GHqqj1zHZqIuy44KCTo0prfqZ6OJZVA=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkN+4AACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrvNRAAkBXAP5cNY/so45Ey2uleztX/qJ4EM7QdQKK4TftftifbN06h\r\nowoLikjqyjUTYhM2FQn+vnPRXJwf27ET1Hm0CixB55bK04stGqy1OJa+Qvvh\r\n/CfN8Z+WcCH9n5N0UhVgA07dzSAbuFgyxc5JOFWUp0G2AssvoMrPmzm0xePC\r\n8FYU0PEne5q8hR7TQ0XrJ1T5bSjGrli9EMYqFjDo1OBjui9ov6oDd9/Hu85M\r\n40ZGO6/QqLeDL4ym3dMvn6uSxs8rwlHyApJ5o0nT7NuDaaJhmcFfGp/ffVK+\r\n+aM1nDElz058fnMorrwuJ21GssUplDMfiUBbFznh6cW91f96wjVCKKPwmfPx\r\n3ZAt4+qJSxl0O9p3iIVoikEUOnZ04eluJysoKmIqplCxW9VslcNpOMzBLoC+\r\nuACYMICqoKz0i+J2asz63oK0DLzcUnyNgx6Z+yA/ce83OOvWRlrAMsqXg7dP\r\nR2h2/UzvwzzZtkR17EH6nQbvtDTILJjl67/2ioPjTWRcrFJYPathBMNkJ/+Q\r\ngwIOXuY5lGMQ94jbd+zlrjQh3kWOQT7KRD+9/LajGHw/e3/3q2JEj34JzU3f\r\nMUW+HkUCKkRAcA+fXeGjSEiqD+VM7xbhrNT4cO8ksQ1XYOFqDaHNh6REi92R\r\nUWd6xIrWVAIcZaFSqGyUhjf4ruBt3g+jndY=\r\n=+LXH\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"joelmoss","email":"joel@developwithstyle.com"},"directories":{},"maintainers":[{"name":"joelmoss","email":"joel@developwithstyle.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ibiza_2.0.0-alpha.13_1681387008197_0.058100753592913446"},"_hasShrinkwrap":false},"2.0.0-alpha.14":{"name":"ibiza","author":{"name":"Joel Moss"},"version":"2.0.0-alpha.14","description":"React State Management for Party Animals","license":"MIT","homepage":"https://github.com/joelmoss/ibiza","repository":{"type":"git","url":"git+https://github.com/joelmoss/ibiza.git"},"bugs":{"url":"https://github.com/joelmoss/ibiza/issues"},"keywords":["react","state","proxy"],"packageManager":"pnpm@8.8.0","type":"module","source":"src/index.js","main":"dist/ibiza.cjs","module":"dist/ibiza.module.js","unpkg":"dist/ibiza.umd.js","exports":{"proscenium":"./src/index.js","require":"./dist/ibiza.cjs","default":"./dist/ibiza.modern.js"},"sideEffects":false,"eslintConfig":{"extends":["eslint:recommended","plugin:react/recommended","plugin:react-hooks/recommended","plugin:prettier/recommended"],"settings":{"react":{"version":"detect"}},"env":{"browser":true,"node":false,"es6":true},"parserOptions":{"ecmaVersion":"latest","sourceType":"module","ecmaFeatures":{"jsx":true}},"rules":{"react/prop-types":0},"overrides":[{"files":["test/**"],"extends":["plugin:jest/recommended","plugin:testing-library/react","plugin:jest/style"],"rules":{"jest/expect-expect":["warn",{"assertFunctionNames":["expect","screen.findByText","screen.getByText"]}]}}]},"size-limit":[{"name":"useIbiza","path":"./src/index.js","import":"{ useIbiza }","limit":"1 s"},{"name":"store","path":"./src/index.js","import":"{ store }","limit":"1 s"},{"name":"createModel","path":"./src/index.js","import":"{ createModel }","limit":"1 s"},{"name":"unproxiedStateOf","path":"./src/index.js","import":"{ unproxiedStateOf }","limit":"1 s"},{"name":"freeze","path":"./src/index.js","import":"{ freeze }","limit":"1 s"}],"prettier":{"trailingComma":"none","printWidth":100,"semi":false,"singleQuote":true,"arrowParens":"avoid"},"peerDependencies":{"react":">=18"},"devDependencies":{"@size-limit/preset-big-lib":"^9.0.0","@swc/core":"^1.3.90","@swc/jest":"^0.2.29","@testing-library/dom":"^9.3.3","@testing-library/jest-dom":"^6.1.3","@testing-library/react":"^14.0.0","@testing-library/user-event":"^14.5.1","cross-fetch":"^4.0.0","eslint":"^8.50.0","eslint-config-prettier":"^9.0.0","eslint-plugin-jest":"^27.4.0","eslint-plugin-prettier":"^5.0.0","eslint-plugin-react":"^7.33.2","eslint-plugin-react-hooks":"^4.6.0","eslint-plugin-testing-library":"^6.0.2","fetch-mock-jest":"^1.5.1","ibiza":"^2.0.0-alpha.13","jest":"^29.7.0","jest-environment-jsdom":"^29.7.0","microbundle":"^0.15.1","msw":"^1.3.1","prettier":"^3.0.3","react":"^18.2.0","react-dom":"^18.2.0","react-error-boundary":"^4.0.11","rimraf":"^5.0.5","size-limit":"^9.0.0"},"dependencies":{"fast-equals":"^5.0.1","micro-memoize":"^4.1.2"},"scripts":{"clean":"rimraf dist","test":"jest","build":"microbundle --jsx React.createElement","dev":"microbundle watch --jsx React.createElement --compress false","size":"microbundle && size-limit","lint":"eslint src test --ext .jsx --ext .js"},"readme":"# Ibiza - React State Management for Party Animals\n\nIbiza gets out of your way and simply lets you read and write state as you would with regular\nJavascript assignment. It maintains a global state object and is smart enough to know when to\nrerender your components based on state usage and modification.\n\n## `useIbiza()` ✨\n\nA component calls the `useIbiza` React hook, which returns the store state as a JS Proxy object.\nThis Proxy records when a state property is accessed or \"used\". Then when that property is mutated,\nthe component is rerendered.\n\nThis means that you can mutate your state in any way, but your component will only rerender if you\nmutate state that you have used.\n\nThe following component will rerender when the button is clicked, because `name` has changed.\n\n```jsx\nimport { useIbiza } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n      <button onClick={() => void (state.name = 'Joel')}></button>\n    </div>\n  )\n}\n```\n\nThe following component will not rerender when the button is clicked, because even though `age` has\nbeen mutated, it is not actually being used within the component.\n\n```jsx\nimport { useIbiza } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n      <button onClick={() => void (state.age = 44)}></button>\n    </div>\n  )\n}\n```\n\nState can be mutated from anywhere - not just from within a component:\n\n```js\nimport { useIbiza, store } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n    </div>\n  )\n}\n\n// <App> component will re-render when this line executes, as `name` has changed.\nstore.state.name = 'Ash'\n```\n\n### Initial State\n\nYou can pass some initial state to `useIbiza` which will be merged with existing state in the Ibiza\nstore.\n\n```jsx\nconst App = () => {\n  const state = useIbiza({ user: { name: 'Joel' } })\n\n  return <h1>Hello {state.user.name}</h1>\n}\n```\n\nThis is safe to include in the body of your component, as it will only be merged into the store on\nfirst render.\n\n### Slicing\n\nIbiza supports deeply nested objects, allowing you to design the shape of your state any way you\nlike. To help you work with such nested state, the `useIbiza` hook supports slicing.\n\nThe following example assumes you have an existing state object:\n\n```javascript\n{\n  user: {\n    name: 'Joel',\n    partner: {\n      name: 'Sam',\n    }\n  }\n}\n```\n\nPass a string to `useIbiza` to fetch a specific slice of state. The string should be the path to the\nobject that you want.\n\n```jsx\nconst App = () => {\n  const partner = useIbiza('user.partner')\n\n  return (\n    <div>\n      <h1>Hello {partner.name}</h1>\n      <button onClick={() => void (partner.name = 'Bob')}></button>\n    </div>\n  )\n}\n```\n\nNote that slicing is really only supported as a convenience, and will not generally help with\nperformance.\n\n## `createModel()`\n\nIbiza is at its most powerful when working with models. They provide reusability and flexibility.\n\nCreate a model using the `createModel` helper, where the first argument is the model name, and the\nsecond argument is the initial model state as a plain object.\n\n```javascript\n// model.js\n\nexport default createModel('user', {\n  firstName: 'Joel',\n  lastName: 'Moss',\n  children: [{ firstName: 'Ash' }, { firstName: 'Elijah' }, { firstName: 'Eve' }]\n})\n```\n\n`createModel` returns a hook which you can use. You can now import your model anywhere:\n\n```jsx\n// app.jsx\n\nimport useModel from './model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <div>\n      <h1>Hello {user.firstName}</h1>\n      <ul>\n        {user.children.map((child, i) => (\n          <li key={i}>{child.firstName}</li>\n        ))}\n      </ul>\n    </div>\n  )\n}\n```\n\n### Initial State\n\nSometimes you want to be able to define your model with some initial state that could be provided\ndynamically. For example, from component props or some other parameters.\n\n`createModel` can accept a function as its second argument. This function will be called on\ninitialisation with two arguments; the current `state` and any `props` passed to it when its hook is\nfirst called.\n\n```javascript\n// model.js\n\nexport default createModel('user', (state, props) => ({\n  firstName: 'Joel',\n  lastName: 'Moss'\n  ...props\n}))\n```\n\n```jsx\n// app.jsx\n\nimport useModel from './model'\n\nconst App = ({ yearOfBirth }) => {\n  const user = useModel({ yearOfBirth })\n\n  return (\n    <div>\n      <h1>\n        Hello {user.firstName}, you were born in {user.yearOfBirth}.\n      </h1>\n    </div>\n  )\n}\n```\n\n### Functions\n\nYou can use regular function in your model. They accept the current state as the first argument, and\n`this` will also be the current state (as long as you don't use hash rocket functions).\n\n```jsx\nconst App = () => {\n  const state = useIbiza({\n    count: 0,\n    increment: state => {\n      ++state.count\n    },\n    decrement() {\n      ++this.count\n    }\n  })\n\n  return (\n    <>\n      <h1>Count = {state.count}</h1>\n      <button onClick={state.increment}>Increment</button>\n      <button onClick={state.decrement}>Decrement</button>\n    </>\n  )\n}\n```\n\nWhen reading/writing state within a function, `this` responds to the state at the level where the\nfunction sits. This means that if the function is deeply nested, `this` will not include state lower\ndown.\n\nTo solve this, you can call `this.$model` to access your model, or `this.$root` to access the root\nof the store state.\n\n```javascript\nuseIbiza({\n  deepstate: {\n    user: {\n      name: 'Joel',\n      partner: {\n        name: 'Sam',\n\n        get partner() {\n          // `this` refers to 'deepstate.user.partner'.\n          // `this.$model` refers to 'deepstate.user'.\n          // `this.$root` is the whole store state.\n          return this.$model.name\n        }\n      }\n    }\n  }\n})\n```\n\nFunctions accept any number of arguments just like regular functions do, but don't forget that the\nfirst argument is always the state.\n\n```jsx\nconst App = () => {\n  const user = useIbiza({\n    children: [],\n    addChild(state, firstName, lastName) {\n      state.children.push({ firstName, lastName }) // or `this.children.push(...)`\n    }\n  })\n\n  return (\n    <>\n      <ul>\n        {user.children.map((child, i) => (\n          <li key={i}>\n            {child.firstName} {child.lastName}\n          </li>\n        ))}\n      </ul>\n      <button onClick={() => user.addChild('Ash', 'Moss')}></button>\n    </>\n  )\n}\n```\n\nNote that used state is not tracked within functions. This avoids unnecessary component re-rendering\nwhen state changes that is used by a function. The function will always use the latest state anyway,\nso no need to track the state that it uses.\n\nThis does however, mean that you should not call functions during rendering - use a getter instead.\n\n### Getters and Setters\n\nIbiza supports Javascript getters and setters in your state and models.\n\n```javascript\nexport default createModel('user', {\n  firstName: 'Joel',\n  lastName: 'Moss',\n\n  get fullName() {\n    // You can read/write to your state via `this`.\n    return `${this.firstName} ${this.lastName}`\n  },\n\n  set fullName(value) {\n    const [firstName, lastName] = value.split(' ')\n\n    this.firstName = firstName\n    this.lastName = lastName\n  }\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <h1>Hello {user.fullName}</h1>\n      <button onClick={() => void (user.fullName = 'Bob Bones')}></button>\n    </>\n  )\n}\n```\n\n### Async Functions\n\nFunctions can be async and/or return Promises, and support React's Suspense by default.\n\n```javascript\nexport default createModel('user', {\n  name: 'Joel',\n\n  async doSomething() {\n    return await someAsyncAction()\n  }\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <h1>Hello {user.fullName}</h1>\n      <button onClick={user.doSomething}></button>\n    </>\n  )\n}\n```\n\nYou can also return a Promise from getters and properties, and the component will suspend until the\nPromise resolves.\n\n```javascript\nexport default createModel('user', {\n  name: 'Joel',\n\n  get father() {\n    return fetchFather() // Returns a Promise\n  },\n\n  mother: fetchMother() // Returns a Promise\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <div>Hello, my father is {user.father}</div>\n      <div>Hello, my mother is {user.mother}</div>\n    </>\n  )\n}\n```\n\n### URL Models\n\nBecause reading and writing to/from the server is so common, Ibiza has support to make this easy\nwith URL Models, similar to react-query. Simply use a valid and relative URL as your model name or\nslice.\n\nThe following will fetch the user from the server at `/user`, suspending the component while it does\nso. The data is fetched only when it does not exist in the store.\n\n```jsx\nconst App = () => {\n  const user = useIbiza('/user')\n\n  return <h1>Hello {user.name}</h1>\n}\n```\n\nYou can safely mutate your model, as all mutations will remain local.\n\nYou can write your model state back to the server using `$save()`. It the server responds with JSON,\nthe model will be updated with that response.\n\n```jsx\nconst App = () => {\n  const user = useIbiza('/user')\n\n  const renameUser = async () => {\n    await user.$save({ body: { name: 'Bob' } })\n  }\n\n  return (\n    <>\n      <h1>Hello {user.name}</h1>\n      <button onClick={renameUser}></button>\n    </>\n  )\n}\n```\n\nURL Models can also be defined with `createModel`, and accept the same arguments:\n\n```javascript\nexport default createModel('/user')\n```\n\n`createModel` returns a hook which you can use. You can now import your model anywhere:\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return <h1>Hello {user.firstName}</h1>\n}\n```\n\nAdditionally, URL models accept a `fetcher` option, which when provided, will be used as the fetch\nfunction for the model:\n\n```javascript\nexport default createModel('/user', {}, { fetcher: myFetchFunction })\n```\n\n## `createContextModel()`\n\nWrap your component in the `IbizaProvider` higher order component, and instead of `createModel()`,\ncreate your model with `createContextModel()` function. The model will automatically be given a\nunique name specific to the wrapped components in IbizaProvider. Just pass the model definition as\nthe first argument. It accepts the same options as `createModel()` for the second argument.\n\n```jsx\nconst useModel = createContextModel(() => ({\n  // Your model definition...\n  name: 'Awesome!'\n}))\n\nconst App = () => {\n  return (\n    <IbizaProvider>\n      <MyComponent />\n    </IbizaProvider>\n  );\n};\n\nconst MyComponent = () => {\n  const model = useModel()\n\n  return <h1>My model is {model.name}</h1>\n};\n```\n\nEach instance of IbizaProvider will use its own state.\n\n```jsx\nconst useFirstModel = createContextModel(() => ({\n  name: 'FIRST!'\n}))\n\nconst useSecondModel = createContextModel(() => ({\n  name: 'SECOND!'\n}))\n\nconst App = () => {\n  return (\n    <>\n      <IbizaProvider>\n        <MyFirstComponent />\n      </IbizaProvider>\n      <IbizaProvider>\n        <MySecondComponent />\n      </IbizaProvider>\n    </>\n  );\n};\n\nconst MyFirstComponent = () => {\n  const model = useFirstModel();\n\n  return <h1>My model is {model.name}</h1>; // My model is FIRST!\n};\n\nconst MySecondComponent = () => {\n  const model = useSecondModel()\n\n  return <h1>My model is {model.name}</h1> // My model is SECOND!\n};\n```\n\n## How Does Ibiza Work?\n\nIt's all thanks to the magic of Unicorns! 🦄\n\n...actually, I lie. In reality, the magic is courtesy of [JavaScript Proxies](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy).\n\nAnytime you call `useIbiza` in a component, a Proxy of the store state is returned. Reading\nproperties from this proxy is recorded, and each property is tracked as being used in the component.\nWe call this the Hook Proxy, as it is specific to the instance of the `useIbiza` hook, and therefore\nthe component it is used within.\n\nYou can read and write from/to the Hook Proxy, as you would any JavaScript object. Reading, or using\na property, will cause the component to re-render when the property's value is mutated. And mutating\na property value will cause any component that has read the same property, to re-render.\n\nThe Hook Proxy wraps the Store Proxy, which contains the actual Ibiza global state. As with the Hook\nProxy, the Store Proxy can be read and written to, and components that have used the state will\nre-render upon mutation. This means you can mutate the state via the Hook Proxy and/or the Store\nProxy. The Store Proxy does not track property usage.\n","readmeFilename":"README.md","_id":"ibiza@2.0.0-alpha.14","_integrity":"sha512-GtWeYu6Ibh6QWdvCajaKvIOdnQYFEg91Rrn/p7KlvilaOAhGH+uLSsS7t8xF3NoY/tVKgZ4vQf4yIXlFgZ2dww==","_resolved":"/private/var/folders/3b/b6pthvr51cg1755k2jxx8www0000gn/T/8db6262f85ab2a3d1c88284d381e5b8e/ibiza-2.0.0-alpha.14.tgz","_from":"file:ibiza-2.0.0-alpha.14.tgz","_nodeVersion":"20.6.0","_npmVersion":"9.8.1","dist":{"integrity":"sha512-GtWeYu6Ibh6QWdvCajaKvIOdnQYFEg91Rrn/p7KlvilaOAhGH+uLSsS7t8xF3NoY/tVKgZ4vQf4yIXlFgZ2dww==","shasum":"68a175d1a9823fd87fa663015552ed7daac8c48e","tarball":"https://registry.npmjs.org/ibiza/-/ibiza-2.0.0-alpha.14.tgz","fileCount":19,"unpackedSize":395708,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCyRFp8C5uF4BZ1hW1W0vWfoCzkYrEFqf2s3an8OcHzuQIhAMzSSOtS9rOBZldiTIMfxVfvErzxSmXKHjUwEYM6wcsp"}]},"_npmUser":{"name":"joelmoss","email":"joel@developwithstyle.com"},"directories":{},"maintainers":[{"name":"joelmoss","email":"joel@developwithstyle.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ibiza_2.0.0-alpha.14_1695817499068_0.35889465317544667"},"_hasShrinkwrap":false},"2.0.0-alpha.15":{"name":"ibiza","author":{"name":"Joel Moss"},"version":"2.0.0-alpha.15","description":"React State Management for Party Animals","license":"MIT","homepage":"https://github.com/joelmoss/ibiza","repository":{"type":"git","url":"git+https://github.com/joelmoss/ibiza.git"},"bugs":{"url":"https://github.com/joelmoss/ibiza/issues"},"keywords":["react","state","proxy"],"packageManager":"pnpm@8.8.0","type":"module","source":"src/index.js","main":"dist/ibiza.cjs","module":"dist/ibiza.module.js","unpkg":"dist/ibiza.umd.js","exports":{"proscenium":"./src/index.js","require":"./dist/ibiza.cjs","default":"./dist/ibiza.modern.js"},"sideEffects":false,"eslintConfig":{"extends":["eslint:recommended","plugin:react/recommended","plugin:react-hooks/recommended","plugin:prettier/recommended"],"settings":{"react":{"version":"detect"}},"env":{"browser":true,"node":false,"es6":true},"parserOptions":{"ecmaVersion":"latest","sourceType":"module","ecmaFeatures":{"jsx":true}},"rules":{"react/prop-types":0},"overrides":[{"files":["test/**"],"extends":["plugin:jest/recommended","plugin:testing-library/react","plugin:jest/style"],"rules":{"jest/expect-expect":["warn",{"assertFunctionNames":["expect","screen.findByText","screen.getByText"]}]}}]},"size-limit":[{"name":"useIbiza","path":"./src/index.js","import":"{ useIbiza }","limit":"1 s"},{"name":"store","path":"./src/index.js","import":"{ store }","limit":"1 s"},{"name":"createModel","path":"./src/index.js","import":"{ createModel }","limit":"1 s"},{"name":"unproxiedStateOf","path":"./src/index.js","import":"{ unproxiedStateOf }","limit":"1 s"},{"name":"freeze","path":"./src/index.js","import":"{ freeze }","limit":"1 s"}],"prettier":{"trailingComma":"none","printWidth":100,"semi":false,"singleQuote":true,"arrowParens":"avoid","jsdocSingleLineComment":false,"jsdocDescriptionWithDot":true,"jsdocSeparateReturnsFromParam":true,"plugins":["prettier-plugin-jsdoc"]},"peerDependencies":{"react":">=18"},"devDependencies":{"@size-limit/preset-big-lib":"^9.0.0","@swc/core":"^1.3.90","@swc/jest":"^0.2.29","@testing-library/dom":"^9.3.3","@testing-library/jest-dom":"^6.1.3","@testing-library/react":"^14.0.0","@testing-library/user-event":"^14.5.1","cross-fetch":"^4.0.0","eslint":"^8.50.0","eslint-config-prettier":"^9.0.0","eslint-plugin-jest":"^27.4.0","eslint-plugin-prettier":"^5.0.0","eslint-plugin-react":"^7.33.2","eslint-plugin-react-hooks":"^4.6.0","eslint-plugin-testing-library":"^6.0.2","fetch-mock-jest":"^1.5.1","ibiza":"^2.0.0-alpha.13","jest":"^29.7.0","jest-environment-jsdom":"^29.7.0","microbundle":"^0.15.1","msw":"^1.3.1","prettier":"^3.0.3","prettier-plugin-jsdoc":"^1.0.2","react":"^18.2.0","react-dom":"^18.2.0","react-error-boundary":"^4.0.11","rimraf":"^5.0.5","size-limit":"^9.0.0"},"dependencies":{"fast-equals":"^5.0.1","micro-memoize":"^4.1.2"},"scripts":{"clean":"rimraf dist","test":"jest","build":"microbundle --jsx React.createElement","dev":"microbundle watch --jsx React.createElement --compress false","size":"microbundle && size-limit","lint":"eslint src test --ext .jsx --ext .js"},"readme":"# Ibiza - React State Management for Party Animals\n\nIbiza gets out of your way and simply lets you read and write state as you would with regular\nJavascript assignment. It maintains a global state object and is smart enough to know when to\nrerender your components based on state usage and modification.\n\n## `useIbiza()` ✨\n\nA component calls the `useIbiza` React hook, which returns the store state as a JS Proxy object.\nThis Proxy records when a state property is accessed or \"used\". Then when that property is mutated,\nthe component is rerendered.\n\nThis means that you can mutate your state in any way, but your component will only rerender if you\nmutate state that you have used.\n\nThe following component will rerender when the button is clicked, because `name` has changed.\n\n```jsx\nimport { useIbiza } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n      <button onClick={() => void (state.name = 'Joel')}></button>\n    </div>\n  )\n}\n```\n\nThe following component will not rerender when the button is clicked, because even though `age` has\nbeen mutated, it is not actually being used within the component.\n\n```jsx\nimport { useIbiza } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n      <button onClick={() => void (state.age = 44)}></button>\n    </div>\n  )\n}\n```\n\nState can be mutated from anywhere - not just from within a component:\n\n```js\nimport { useIbiza, store } from 'ibiza'\n\nconst App = () => {\n  const state = useIbiza()\n\n  return (\n    <div>\n      <h1>Hello {state.name}</h1>\n    </div>\n  )\n}\n\n// <App> component will re-render when this line executes, as `name` has changed.\nstore.state.name = 'Ash'\n```\n\n### Initial State\n\nYou can pass some initial state to `useIbiza` which will be merged with existing state in the Ibiza\nstore.\n\n```jsx\nconst App = () => {\n  const state = useIbiza({ user: { name: 'Joel' } })\n\n  return <h1>Hello {state.user.name}</h1>\n}\n```\n\nThis is safe to include in the body of your component, as it will only be merged into the store on\nfirst render.\n\n### Slicing\n\nIbiza supports deeply nested objects, allowing you to design the shape of your state any way you\nlike. To help you work with such nested state, the `useIbiza` hook supports slicing.\n\nThe following example assumes you have an existing state object:\n\n```javascript\n{\n  user: {\n    name: 'Joel',\n    partner: {\n      name: 'Sam',\n    }\n  }\n}\n```\n\nPass a string to `useIbiza` to fetch a specific slice of state. The string should be the path to the\nobject that you want.\n\n```jsx\nconst App = () => {\n  const partner = useIbiza('user.partner')\n\n  return (\n    <div>\n      <h1>Hello {partner.name}</h1>\n      <button onClick={() => void (partner.name = 'Bob')}></button>\n    </div>\n  )\n}\n```\n\nNote that slicing is really only supported as a convenience, and will not generally help with\nperformance.\n\n## `createModel()`\n\nIbiza is at its most powerful when working with models. They provide reusability and flexibility.\n\nCreate a model using the `createModel` helper, where the first argument is the model name, and the\nsecond argument is the initial model state as a plain object.\n\n```javascript\n// model.js\n\nexport default createModel('user', {\n  firstName: 'Joel',\n  lastName: 'Moss',\n  children: [{ firstName: 'Ash' }, { firstName: 'Elijah' }, { firstName: 'Eve' }]\n})\n```\n\n`createModel` returns a hook which you can use. You can now import your model anywhere:\n\n```jsx\n// app.jsx\n\nimport useModel from './model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <div>\n      <h1>Hello {user.firstName}</h1>\n      <ul>\n        {user.children.map((child, i) => (\n          <li key={i}>{child.firstName}</li>\n        ))}\n      </ul>\n    </div>\n  )\n}\n```\n\n### Initial State\n\nSometimes you want to be able to define your model with some initial state that could be provided\ndynamically. For example, from component props or some other parameters.\n\n`createModel` can accept a function as its second argument. This function will be called on\ninitialisation with two arguments; the current `state` and any `props` passed to it when its hook is\nfirst called.\n\n```javascript\n// model.js\n\nexport default createModel('user', (state, props) => ({\n  firstName: 'Joel',\n  lastName: 'Moss'\n  ...props\n}))\n```\n\n```jsx\n// app.jsx\n\nimport useModel from './model'\n\nconst App = ({ yearOfBirth }) => {\n  const user = useModel({ yearOfBirth })\n\n  return (\n    <div>\n      <h1>\n        Hello {user.firstName}, you were born in {user.yearOfBirth}.\n      </h1>\n    </div>\n  )\n}\n```\n\n### Functions\n\nYou can use regular function in your model. They accept the current state as the first argument, and\n`this` will also be the current state (as long as you don't use hash rocket functions).\n\n```jsx\nconst App = () => {\n  const state = useIbiza({\n    count: 0,\n    increment: state => {\n      ++state.count\n    },\n    decrement() {\n      ++this.count\n    }\n  })\n\n  return (\n    <>\n      <h1>Count = {state.count}</h1>\n      <button onClick={state.increment}>Increment</button>\n      <button onClick={state.decrement}>Decrement</button>\n    </>\n  )\n}\n```\n\nWhen reading/writing state within a function, `this` responds to the state at the level where the\nfunction sits. This means that if the function is deeply nested, `this` will not include state lower\ndown.\n\nTo solve this, you can call `this.$model` to access your model, or `this.$root` to access the root\nof the store state.\n\n```javascript\nuseIbiza({\n  deepstate: {\n    user: {\n      name: 'Joel',\n      partner: {\n        name: 'Sam',\n\n        get partner() {\n          // `this` refers to 'deepstate.user.partner'.\n          // `this.$model` refers to 'deepstate.user'.\n          // `this.$root` is the whole store state.\n          return this.$model.name\n        }\n      }\n    }\n  }\n})\n```\n\nFunctions accept any number of arguments just like regular functions do, but don't forget that the\nfirst argument is always the state.\n\n```jsx\nconst App = () => {\n  const user = useIbiza({\n    children: [],\n    addChild(state, firstName, lastName) {\n      state.children.push({ firstName, lastName }) // or `this.children.push(...)`\n    }\n  })\n\n  return (\n    <>\n      <ul>\n        {user.children.map((child, i) => (\n          <li key={i}>\n            {child.firstName} {child.lastName}\n          </li>\n        ))}\n      </ul>\n      <button onClick={() => user.addChild('Ash', 'Moss')}></button>\n    </>\n  )\n}\n```\n\nNote that used state is not tracked within functions. This avoids unnecessary component re-rendering\nwhen state changes that is used by a function. The function will always use the latest state anyway,\nso no need to track the state that it uses.\n\nThis does however, mean that you should not call functions during rendering - use a getter instead.\n\n### Getters and Setters\n\nIbiza supports Javascript getters and setters in your state and models.\n\n```javascript\nexport default createModel('user', {\n  firstName: 'Joel',\n  lastName: 'Moss',\n\n  get fullName() {\n    // You can read/write to your state via `this`.\n    return `${this.firstName} ${this.lastName}`\n  },\n\n  set fullName(value) {\n    const [firstName, lastName] = value.split(' ')\n\n    this.firstName = firstName\n    this.lastName = lastName\n  }\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <h1>Hello {user.fullName}</h1>\n      <button onClick={() => void (user.fullName = 'Bob Bones')}></button>\n    </>\n  )\n}\n```\n\n### Async Functions\n\nFunctions can be async and/or return Promises, and support React's Suspense by default.\n\n```javascript\nexport default createModel('user', {\n  name: 'Joel',\n\n  async doSomething() {\n    return await someAsyncAction()\n  }\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <h1>Hello {user.fullName}</h1>\n      <button onClick={user.doSomething}></button>\n    </>\n  )\n}\n```\n\nYou can also return a Promise from getters and properties, and the component will suspend until the\nPromise resolves.\n\n```javascript\nexport default createModel('user', {\n  name: 'Joel',\n\n  get father() {\n    return fetchFather() // Returns a Promise\n  },\n\n  mother: fetchMother() // Returns a Promise\n})\n```\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return (\n    <>\n      <div>Hello, my father is {user.father}</div>\n      <div>Hello, my mother is {user.mother}</div>\n    </>\n  )\n}\n```\n\n### URL Models\n\nBecause reading and writing to/from the server is so common, Ibiza has support to make this easy\nwith URL Models, similar to react-query. Simply use a valid and relative URL as your model name or\nslice.\n\nThe following will fetch the user from the server at `/user`, suspending the component while it does\nso. The data is fetched only when it does not exist in the store.\n\n```jsx\nconst App = () => {\n  const user = useIbiza('/user')\n\n  return <h1>Hello {user.name}</h1>\n}\n```\n\nYou can safely mutate your model, as all mutations will remain local.\n\nYou can write your model state back to the server using `$save()`. It the server responds with JSON,\nthe model will be updated with that response.\n\n```jsx\nconst App = () => {\n  const user = useIbiza('/user')\n\n  const renameUser = async () => {\n    await user.$save({ body: { name: 'Bob' } })\n  }\n\n  return (\n    <>\n      <h1>Hello {user.name}</h1>\n      <button onClick={renameUser}></button>\n    </>\n  )\n}\n```\n\nURL Models can also be defined with `createModel`, and accept the same arguments:\n\n```javascript\nexport default createModel('/user')\n```\n\n`createModel` returns a hook which you can use. You can now import your model anywhere:\n\n```jsx\nimport useModel from './user_model'\n\nconst App = () => {\n  const user = useModel()\n\n  return <h1>Hello {user.firstName}</h1>\n}\n```\n\nAdditionally, URL models accept a `fetcher` option, which when provided, will be used as the fetch\nfunction for the model:\n\n```javascript\nexport default createModel('/user', {}, { fetcher: myFetchFunction })\n```\n\n## `createContextModel()`\n\nWrap your component in the `IbizaProvider` higher order component, and instead of `createModel()`,\ncreate your model with `createContextModel()` function. The model will automatically be given a\nunique name specific to the wrapped components in IbizaProvider. Just pass the model definition as\nthe first argument. It accepts the same options as `createModel()` for the second argument.\n\n```jsx\nconst useModel = createContextModel(() => ({\n  // Your model definition...\n  name: 'Awesome!'\n}))\n\nconst App = () => {\n  return (\n    <IbizaProvider>\n      <MyComponent />\n    </IbizaProvider>\n  );\n};\n\nconst MyComponent = () => {\n  const model = useModel()\n\n  return <h1>My model is {model.name}</h1>\n};\n```\n\nEach instance of IbizaProvider will use its own state.\n\n```jsx\nconst useFirstModel = createContextModel(() => ({\n  name: 'FIRST!'\n}))\n\nconst useSecondModel = createContextModel(() => ({\n  name: 'SECOND!'\n}))\n\nconst App = () => {\n  return (\n    <>\n      <IbizaProvider>\n        <MyFirstComponent />\n      </IbizaProvider>\n      <IbizaProvider>\n        <MySecondComponent />\n      </IbizaProvider>\n    </>\n  );\n};\n\nconst MyFirstComponent = () => {\n  const model = useFirstModel();\n\n  return <h1>My model is {model.name}</h1>; // My model is FIRST!\n};\n\nconst MySecondComponent = () => {\n  const model = useSecondModel()\n\n  return <h1>My model is {model.name}</h1> // My model is SECOND!\n};\n```\n\n## How Does Ibiza Work?\n\nIt's all thanks to the magic of Unicorns! 🦄\n\n...actually, I lie. In reality, the magic is courtesy of [JavaScript Proxies](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy).\n\nAnytime you call `useIbiza` in a component, a Proxy of the store state is returned. Reading\nproperties from this proxy is recorded, and each property is tracked as being used in the component.\nWe call this the Hook Proxy, as it is specific to the instance of the `useIbiza` hook, and therefore\nthe component it is used within.\n\nYou can read and write from/to the Hook Proxy, as you would any JavaScript object. Reading, or using\na property, will cause the component to re-render when the property's value is mutated. And mutating\na property value will cause any component that has read the same property, to re-render.\n\nThe Hook Proxy wraps the Store Proxy, which contains the actual Ibiza global state. As with the Hook\nProxy, the Store Proxy can be read and written to, and components that have used the state will\nre-render upon mutation. This means you can mutate the state via the Hook Proxy and/or the Store\nProxy. The Store Proxy does not track property usage.\n","readmeFilename":"README.md","_id":"ibiza@2.0.0-alpha.15","_integrity":"sha512-LkT952eMvLNVgSGUM7LTHuQI/XaPJNfh5PgoDP+unOncAsgBngp9ttpj0diJ7Fmw0gs1HBUq4jx0Fm3IE9yMqw==","_resolved":"/private/var/folders/3b/b6pthvr51cg1755k2jxx8www0000gn/T/ba8f4e6e1ddba474c7479797c88ef502/ibiza-2.0.0-alpha.15.tgz","_from":"file:ibiza-2.0.0-alpha.15.tgz","_nodeVersion":"20.6.0","_npmVersion":"9.8.1","dist":{"integrity":"sha512-LkT952eMvLNVgSGUM7LTHuQI/XaPJNfh5PgoDP+unOncAsgBngp9ttpj0diJ7Fmw0gs1HBUq4jx0Fm3IE9yMqw==","shasum":"82d986a87bed5aab17489cbda5fb0e1907ca31c5","tarball":"https://registry.npmjs.org/ibiza/-/ibiza-2.0.0-alpha.15.tgz","fileCount":19,"unpackedSize":397957,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAT+uv5FF0vzPIgA9APeAxvrsJOsQphOuZkveLoTT15GAiEAkx/pxXvgeuHzzC03BZfqHeuZbjq8ZCZjR+K6OmNY+k0="}]},"_npmUser":{"name":"joelmoss","email":"joel@developwithstyle.com"},"directories":{},"maintainers":[{"name":"joelmoss","email":"joel@developwithstyle.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ibiza_2.0.0-alpha.15_1696432445131_0.9208685867596407"},"_hasShrinkwrap":false}},"time":{"created":"2021-11-17T22:56:20.048Z","1.0.0-beta.1":"2021-11-17T22:56:20.236Z","modified":"2023-10-04T15:14:05.529Z","1.0.0-beta.2":"2021-11-18T01:05:44.489Z","1.0.0-beta.3":"2021-11-18T22:29:45.731Z","1.0.0-beta.4":"2021-11-18T22:33:03.276Z","1.0.0-beta.5":"2021-11-18T22:39:06.477Z","1.0.0-beta.6":"2021-11-18T22:44:53.007Z","1.0.0-beta.7":"2021-11-18T23:00:33.357Z","1.0.0-beta.8":"2021-11-18T23:04:48.727Z","1.0.0-beta.9":"2021-11-18T23:59:35.211Z","1.0.0":"2021-11-23T15:59:18.192Z","1.1.0":"2021-11-30T15:30:51.988Z","1.1.1":"2022-01-12T12:15:07.965Z","1.1.2":"2022-02-01T12:07:26.654Z","1.1.3":"2022-02-02T14:39:32.394Z","1.1.4":"2022-02-02T21:57:34.600Z","1.1.5":"2022-02-09T21:59:01.447Z","1.2.0":"2022-02-18T10:55:34.985Z","1.3.0":"2022-02-23T00:58:05.177Z","1.3.1-0":"2022-02-23T01:14:08.116Z","1.4.0-0":"2022-02-23T01:14:38.373Z","1.5.0-0":"2022-02-23T01:18:16.029Z","1.3.0-0":"2022-02-23T01:25:51.327Z","1.3.1":"2022-02-25T09:12:59.102Z","1.3.2":"2022-05-24T14:12:12.973Z","1.4.0":"2022-05-27T00:01:03.692Z","1.5.0":"2022-06-07T15:59:08.850Z","1.5.1":"2022-06-15T10:48:14.101Z","2.0.0-alpha.1":"2022-06-22T15:17:08.547Z","2.0.0-alpha.2":"2022-06-22T17:59:39.286Z","2.0.0-alpha.3":"2022-06-28T14:22:49.139Z","2.0.0-alpha.4":"2022-06-28T16:03:09.011Z","2.0.0-alpha.5":"2022-06-28T16:35:51.942Z","2.0.0-alpha.6":"2022-06-29T09:54:00.261Z","2.0.0-alpha.7":"2022-06-29T16:42:59.057Z","2.0.0-alpha.8":"2022-07-04T15:08:30.402Z","2.0.0-alpha.9":"2022-07-27T14:05:16.751Z","2.0.0-alpha.10":"2022-09-05T09:39:55.045Z","2.0.0-alpha.11":"2022-09-28T09:31:47.269Z","2.0.0-alpha.12":"2022-11-16T19:50:28.197Z","2.0.0-alpha.13":"2023-04-13T11:56:48.352Z","2.0.0-alpha.14":"2023-09-27T12:24:59.302Z","2.0.0-alpha.15":"2023-10-04T15:14:05.359Z"},"maintainers":[{"name":"joelmoss","email":"joel@developwithstyle.com"}],"description":"React State Management for Party Animals","homepage":"https://github.com/joelmoss/ibiza","keywords":["react","state","proxy"],"repository":{"type":"git","url":"https://github.com/joelmoss/ibiza.git"},"author":{"name":"Joel Moss"},"bugs":{"url":"https://github.com/joelmoss/ibiza/issues"},"license":"MIT","readme":"","readmeFilename":""}