{"id":17374144,"url":"https://github.com/alloc/ople","last_synced_at":"2025-02-27T02:30:56.171Z","repository":{"id":57315695,"uuid":"268295375","full_name":"alloc/ople","owner":"alloc","description":"Event-driven, observable data flow for React 💥👀","archived":false,"fork":false,"pushed_at":"2023-10-16T17:31:56.000Z","size":1035,"stargazers_count":9,"open_issues_count":13,"forks_count":0,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-09-16T18:39:59.058Z","etag":null,"topics":["data-flow","event-driven","observable","reactjs","state-management"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/alloc.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-05-31T14:20:10.000Z","updated_at":"2022-08-21T08:29:35.000Z","dependencies_parsed_at":"2022-09-18T20:52:51.657Z","dependency_job_id":null,"html_url":"https://github.com/alloc/ople","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alloc%2Fople","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alloc%2Fople/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alloc%2Fople/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alloc%2Fople/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alloc","download_url":"https://codeload.github.com/alloc/ople/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":219842549,"owners_count":16556534,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["data-flow","event-driven","observable","reactjs","state-management"],"created_at":"2024-10-16T03:04:13.281Z","updated_at":"2024-10-16T03:04:13.892Z","avatar_url":"https://github.com/alloc.png","language":"TypeScript","funding_links":["https://paypal.me/alecdotbiz"],"categories":[],"sub_categories":[],"readme":"# ople\n\n[![npm](https://img.shields.io/npm/v/ople.svg)](https://www.npmjs.com/package/ople)\n[![Build status](https://travis-ci.org/alloc/ople.svg?branch=master)](https://travis-ci.org/alloc/ople)\n[![codecov](https://codecov.io/gh/alloc/ople/branch/master/graph/badge.svg)](https://codecov.io/gh/alloc/ople)\n[![Bundle size](https://badgen.net/bundlephobia/min/ople)](https://bundlephobia.com/result?p=ople)\n[![Code style: Prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg)](https://github.com/prettier/prettier)\n[![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://paypal.me/alecdotbiz)\n\nEvent-driven, observable data flow for React 💥👀\n\n**Features**\n\n- Transparent observability for seamless, reactive data flow\n- Automatic disposal of event listeners and `auto` reactions\n- Compatible with all [`wana`](https://github.com/alloc/wana) functions\n- Mixins for sharable behavior (inspired by React hooks)\n- Strict type safety with TypeScript\n- Objects are readonly outside their initializer\n- Objects have built-in event emitting\n- Highly minifiable code\n- Concise, distilled API\n\n\u0026nbsp;\n\n## Usage\n\nThe `createOple` function constructs an Ople object, which is both observable\nand readonly to React components. Expose methods for React components to call,\nand expose events for React components to subscribe to.\n\n```tsx\nimport {createOple, auto} from 'ople'\n\n// Pass an initializer function to receive a state object,\n// a set function, and an emit function.\nconst state = createOple((self, set, emit) =\u003e {\n  // The state is mutable.\n  self.a = 1\n\n  // The state is observable.\n  auto(() =\u003e {\n    console.log('a:', self.a)\n  })\n\n  // The set function is a shortcut for `Object.assign(self, {...})`\n  set({ b: 1, c: 1 })\n\n  // The set function converts every getter into an observable getter (unless a setter exists).\n  set({\n    get sum() {\n      return self.a + self.b + self.c\n    }\n  })\n  auto(() =\u003e {\n    console.log('sum:', self.sum)\n  })\n\n  // The set function is the recommended way of declaring methods.\n  set({\n    // Methods declared with `set` are wrapped to disable implicit observation\n    // and to set the Ople context until the method returns.\n    add(key: string, n: number) {\n      self[key] += n\n\n      // The emit function is a shortcut for `self.emit(...)`\n      emit('add', key, n)\n    }\n  })\n\n  // Subscribe to your own events or the events of another Ople object.\n  // Your listeners are removed when the built-in `dispose` method is called.\n  self.on({\n    add(key, n) {\n      console.log('add:', key, n)\n    }\n  })\n})\n\n// The state is observable outside the initializer, too.\nauto(() =\u003e {\n  console.log('b:', state.b)\n})\n\nstate.add('b', 2)\n\n// Clean up any side effects.\nstate.dispose()\n```\n\n\u0026nbsp;\n\n## Classes\n\nIf you like creating objects with `new` syntax or you prefer storing your methods\non a prototype for efficiency, you can create an `Ople` subclass. For more info,\nsee the [Classes](./docs/classes.md) page.\n\n\u0026nbsp;\n\n## Mixins\n\nAs an alternative to classes (which limit you to a single superclass), you can\nuse \"mixin functions\" to share behavior between your Ople objects. Mixins should\nbe very familiar to anyone who uses React hooks. Just remember, mixins are **NOT**\nsubject to the same rules as React hooks. For example, mixins can be called from\nwithin `if` blocks. The **only rule** of mixins is that you should only ever call\nthem from within an Ople context (eg: inside a `createOple` initializer).\n\nFor more info, see the [Mixins](./docs/mixins.md) page.\n\n\u0026nbsp;\n\n## FAQ\n\nThese questions are common for beginners to ask. If you have a question not yet\nlisted here, feel free to open a pull request, and I'll add an answer to it.\n\n- **Why are Ople objects readonly outside their initializer?**\n\n  To keep mutations local to the state they are acting upon. This makes it\n  easy to remember which module contains the code you are concerned with.\n  It also encourages you to declare reusable methods instead of duplicating\n  logic across your project. Your methods will be implicitly bound to their\n  local state, which means you won't have to manually `.bind` them before\n  using them as React element props (eg: `onClick`).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falloc%2Fople","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falloc%2Fople","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falloc%2Fople/lists"}