{"id":13727434,"url":"https://github.com/nezaboodka/reactronic","last_synced_at":"2026-04-03T00:04:25.373Z","repository":{"id":37432448,"uuid":"170656406","full_name":"nezaboodka/reactronic","owner":"nezaboodka","description":"Transactionally Reactive State Management for JavaScript","archived":false,"fork":false,"pushed_at":"2026-01-21T09:27:31.000Z","size":9236,"stargazers_count":24,"open_issues_count":4,"forks_count":4,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-01-21T21:13:36.563Z","etag":null,"topics":["javascript","react","reactive-programming","state-management","transactional-reactivity","transactions"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nezaboodka.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":"NOTICE","maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2019-02-14T08:36:07.000Z","updated_at":"2026-01-21T09:27:35.000Z","dependencies_parsed_at":"2023-11-22T11:28:16.234Z","dependency_job_id":"29f8d7ac-3735-4e45-9e05-637ea030c3a9","html_url":"https://github.com/nezaboodka/reactronic","commit_stats":{"total_commits":2843,"total_committers":6,"mean_commits":473.8333333333333,"dds":0.008090045726345418,"last_synced_commit":"ac30b6931e18460f91c219be373ad655eff50fa2"},"previous_names":[],"tags_count":146,"template":false,"template_full_name":null,"purl":"pkg:github/nezaboodka/reactronic","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nezaboodka%2Freactronic","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nezaboodka%2Freactronic/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nezaboodka%2Freactronic/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nezaboodka%2Freactronic/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nezaboodka","download_url":"https://codeload.github.com/nezaboodka/reactronic/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nezaboodka%2Freactronic/sbom","scorecard":{"id":668320,"data":{"date":"2025-08-11","repo":{"name":"github.com/nezaboodka/reactronic","commit":"04b5f5f8d90069c023e09852ec375f260c1c3dc0"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":5.2,"checks":[{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/release.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Maintained","score":10,"reason":"30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Pinned-Dependencies","score":3,"reason":"dependency not pinned by hash detected -- score normalized to 3","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:9: update your workflow using https://app.stepsecurity.io/secureworkflow/nezaboodka/reactronic/release.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:10: update your workflow using https://app.stepsecurity.io/secureworkflow/nezaboodka/reactronic/release.yml/master?enable=pin","Info:   0 out of   2 GitHub-owned GitHubAction dependencies pinned","Info:   1 out of   1 npmCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Packaging","score":10,"reason":"packaging workflow detected","details":["Info: Project packages its releases by way of GitHub Actions.: .github/workflows/release.yml:6"],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Vulnerabilities","score":8,"reason":"2 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-xffm-g5w8-qvg7","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-21T18:58:48.959Z","repository_id":37432448,"created_at":"2025-08-21T18:58:48.959Z","updated_at":"2025-08-21T18:58:48.959Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28752487,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-25T10:25:12.305Z","status":"ssl_error","status_checked_at":"2026-01-25T10:25:11.933Z","response_time":113,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["javascript","react","reactive-programming","state-management","transactional-reactivity","transactions"],"created_at":"2024-08-03T01:03:55.994Z","updated_at":"2026-01-25T11:05:40.743Z","avatar_url":"https://github.com/nezaboodka.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"﻿\n[![Readiness](https://img.shields.io/badge/release-beta-red.svg)](https://en.wikipedia.org/wiki/Software_release_life_cycle#Release_candidate)\n[![GitHub License](https://img.shields.io/badge/license-Apache2-4cc61e.svg?style=flat)](https://github.com/nezaboodka/reactronic/blob/master/LICENSE)\n[![NPM Version](https://img.shields.io/npm/v/reactronic.svg?style=flat\u0026colorB=success)](https://www.npmjs.com/package/reactronic)\n[![Package Size](https://img.shields.io/bundlephobia/minzip/reactronic.svg?colorB=success)](https://bundlephobia.com/result?p=reactronic)\n![Coverage](https://img.shields.io/badge/coverage-97%25-success.svg)\n![Lines](https://img.shields.io/badge/lines-2722-success.svg)\n[![Demo](https://img.shields.io/badge/demo-live-success.svg)](https://gitlab.com/nezaboodka/nevod.website/-/blob/master/README.md)\n\n# **Reactronic** - Transactional Reactive State Management\n\nReactronic is an experimental JavaScript library that provides\n[transactional reactive](https://blog.nezaboodka.com/post/2019/593-modern-database-should-natively-support-transactionally-reactive-programming)\nstate management in a Web application.\n\nTransactional reactivity means that state changes are\nbeing made in an isolated data snapshot and then, once\natomically applied, are **consistently propagated** to\ncorresponding visual components for (re)rendering. All\nthat is done in automatic, seamless, and fine-grained\nway. Reactronic **takes full care of tracking dependencies**\nbetween visual components (reactive functions) and\napplication state (signalling objects).\n\nTransactional reactivity is based on four fundamental\nconcepts:\n\n  - **Signalling Objects** - a set of objects that store\n    data of an application (state) and cause reactions\n    upon their changes;\n  - **Transactional Function** - a function that makes\n    changes in signalling objects in atomic way (\"all\n    or nothing\");\n  - **Reactive Function** - a function that is\n    (re-)executed in response to changes made in\n    signalling objects by transactional functions;\n  - **Cache Function** -  a function which result is\n    remembered and, if becomes obsolete, causes\n    function to re-execute on-demand.\n\nDemo application built with Reactronic: https://nevod.io/#/playground.\nSource code of the demo: https://gitlab.com/nezaboodka/nevod.web.public/-/blob/master/README.md.\n\nQuick introduction and detailed description is below.\n\n## Quick Introduction\n\nHere is an example of transactional reactive code:\n\n``` typescript\nclass Demo extends RxObject {\n  name: string = 'Nezaboodka Software'\n  email: string = 'contact@nezaboodka.com'\n\n  @transaction\n  saveContact(name: string, email: string): void {\n    this.name = name\n    this.email = email\n  }\n\n  @reaction\n  printContact(): void {\n    // depends on `name` and `email` and reacts to their changes\n    if (this.email.indexOf('@') \u003e= 0)\n      throw new Error(`wrong email ${this.email}`)\n    console.log(this.name + ' \u003c' + this.email + '\u003e')\n  }\n}\n```\n\nIn the example above, `Demo` is a signalling object,\nmeaning that access to its fields are seamlessly tracked\nto determine dependent reactive and cached functions.\nReactive function `printContact` reads `name` and `email`\nfields, thus depends on them. It is executed automatically\nin response to changes of these fields made by the\ntransactional function `saveContact`.\n\nHere is an example of a cached result that is\n(re-)computed on-demand:\n\n``` typescript\nclass Demo extends SignallingObject {\n  name: string = 'Nezaboodka Software'\n  email: string = 'contact@nezaboodka.com'\n\n  @cache\n  get contact(): string {\n    return this.name + ' \u003c' + this.email + '\u003e'\n  }\n\n  @reaction\n  printContact(): void {\n    if (this.contact !== '')\n      Console.log(this.contact)\n  }\n}\n```\n\nIn the example above, the result of `contact` getter is\ncomputed from source fields `name` and `email`. Once\ncomputed, the result is cached and is reused until\nsource fields `name` and `email` are changed. Once\nsource fields changed, `contact` result becomes obsolete,\nthus causing execution of depending reactive function\n`printContact`. When function of reactive function\n`printContact` runs it reads `contact` and causes its\nre-computation.\n\n## Signalling Objects\n\nSignalling objects are aimed to store data of\nan application. All such objects are transparently hooked\nto track access to their properties, both on reads and\nwrites.\n\n``` typescript\nclass MyModel extends RxObject {\n  url: string = \"https://github.com/nezaboodka/reactronic\"\n  content: string = \"transactional reactive state management\"\n  timestamp: Date = Date.now()\n}\n```\n\nIn the example above, the class `MyModel` is based on\nReactronic's `RxObject` class and all its\nproperties `url`, `content`, and `timestamp` are hooked.\n\n## Transactional Function\n\nTransactional function makes changes in signalling\nobjects in atomic way (\"all or nothing\"), thus provoking\nexecution of dependent reactive and cached functions.\nTransactional function is instrumented with hooks to\nprovide transparent atomicity (by implicit context\nswitching and isolation).\n\n``` typescript\nclass MyModel extends RxObject {\n  // ...\n  @transaction\n  async load(url: string): Promise\u003cvoid\u003e {\n    this.url = url\n    this.content = await fetch(url)\n    this.timestamp = Date.now()\n  }\n}\n```\n\nIn the example above, the transactional function `load` makes\nchanges to `url`, `content` and `timestamp` properties.\nWhile transactional function is running, the changes are visible\nonly inside the function itself. The new values become\natomically visible outside of the function only upon its\ncompletion.\n\nAtomicity is achieved by making changes in an isolated\ndata snapshot that is not visible outside of the running\nfunction until it is fully finished and applied. Multiple\nobjects and their properties can be changed with full\nrespect to the all-or-nothing principle. To do so,\nseparate data snapshot is automatically maintained for\neach transactional function. That is a logical snapshot\nthat does not create a full copy of all the data.\n\nCompensating rollback operations are not needed in case\nof a transactional function failure, because all the changes\nmade by transactional function in its logical snapshot are\nsimply discarded. In case a transaction function is\nsuccessfully applied, affected cached results are marked\nas obsolete and corresponding caching functions are\nre-executed in a proper order (but only when all the\ndata changes are fully applied).\n\nAsynchronous operations (promises) are supported out of\nthe box during transactional function execution.\nTransactional function may consist of a set of asynchronous\ncalls prolonging the function until completion of all of\nthem. An asynchronous call may spawn other asynchronous\ncalls, which prolong transactional execution until the whole\nchain of asynchronous operations is fully completed.\n\n## Reactive \u0026 Cached Functions\n\nReactive function is automatically and immediately called\nin response to changes in signalling objects made by\ntransactional functions. Cached function is called on-demand\nto renew the result if it was marked as obsolete due to\nchanges made by an transactional functions. Reactive and cached\nfunctions are instrumented with hooks to seamless\nlistening of those signalling objects and other cached\nfunctions (dependencies), which are used during their\nexecution.\n\n``` tsx\nclass MyView extends Component\u003c{model: MyModel}\u003e {\n  @cache\n  render(): React.JSX.Element {\n    return (\n      \u003cdiv\u003e\n        \u003ch1\u003e{this.props.model.url}\u003c/h1\u003e\n        \u003cdiv\u003e{this.props.model.content}\u003c/div\u003e\n      \u003c/div\u003e\n    )\n  } // render is listening to \"url\" and \"content\"\n}\n```\n\n``` tsx\nclass Component\u003cP\u003e extends React.Component\u003cP\u003e {\n  @cache\n  render(): React.JSX.Element {\n    throw new Error('render method is undefined')\n  }\n\n  @reaction // called in response to changes\n  ensureUpToDate(): void {\n    if (this.shouldComponentUpdate()) {\n      // Ask React to re-render\n      Transaction.outside(() =\u003e this.setState({}))\n    }\n  } // EnsureUpToDate is listening to render\n\n  shouldComponentUpdate(): boolean {\n    const r = manageReaction(this.render)\n    return !r.isUpToDate\n  }\n\n  componentDidMount(): void {\n    // Run for the first time to start listening\n    this.ensureUpToDate()\n  }\n\n  componentWillUnmount(): void {\n    runTransactional(disposeRxObject, this)\n  }\n}\n```\n\nIn the example above, reactive function `refresh`\ntransparently listens to the cached function `render`.\nIn turn, cached function `render` listens to the\nproperties `url` and `content` of a corresponding `MyModel`\nobject. Once `url` or `content` values are changed, the\ncached function `render` becomes obsolete and causes the\nreactive function `refresh` to become obsolete and\nre-executed. While being executed, the reactive function\n`refresh` enqueues re-rendering request to React, which\ncalls cached function `render` causing it to renew its\ncached value.\n\nIn general case, all reactive and cached functions\nare automatically and immediately marked as obsolete\nwhen changes are made in those signalling objects and\nother cached results that were used during their\nexecution. And once marked, the functions are\nautomatically executed again, either immediately (for\nreactive functions) or on-demand (for cached functions).\n\nReactronic takes full care of tracking dependencies\nbetween all the signalling objects and reactive/cached\nfunctions. With Reactronic, you no longer need to create\ndata change events in one set of objects, listen to\nthese events in other objects, and manually maintain\nswitching from the previous object version to a new one.\n\n## Behavior Options\n\nThere are multiple options to configure behavior of\ntransactional reactivity.\n\n**Order** options defines order of execution for\nreactive functions:\n\n  - (TBD)\n\n**Throttling** option defines how often reactive function\nis executed in case of recurring changes:\n\n  - `(ms)` - minimal delay in milliseconds between executions;\n  - `-1` - execute immediately once transactional function changes are applied (synchronously);\n  - `0` - execute immediately via event loop (asynchronously with zero timeout);\n  - `\u003e= Number.MAX_SAFE_INTEGER` - never execute (suspended reaction).\n\n**Reentrance** option defines how to handle reentrant calls of transactional\nand reactive functions:\n\n  - `preventWithError` - fail with error if there is an existing call in progress;\n  - `waitAndRestart` - wait for previous call to finish and then restart current one;\n  - `cancelPrevious` - cancel previous call in favor of recent one;\n  - `cancelAndWaitPrevious` - cancel previous call in favor of recent one (but wait until canceling is completed)\n  - `runSideBySide` - multiple simultaneous calls are allowed.\n\n**Indicator** is an object that maintains status of running functions,\nwhich it is attached to. A single indicator object can be shared between\nmultiple transactional, reactive, and cached functions, thus maintaining\nconsolidated status for all of them (busy, workers, etc).\n\n## Notes\n\nInspired by: MobX, Nezaboodka, Excel.\n\nKey Reactronic principles and differentiators:\n\n  - No compromises on consistency, clarity, and simplicity;\n  - Minimalism and zero boilerplating (it's not a framework bloating your code);\n  - Async, patches, undo/redo, conflict resolving are provided out of the box;\n  - Seamless integration with transactional reactive object-oriented databases like [Nezaboodka](https://nezaboodka.com/#products);\n  - Compact dependency-free implementation consisting of less than 2K lines of code.\n\nRoadmap:\n\n  - Patches and conflict resolution API (partially done)\n  - History/undo/redo API and implementation (partially done)\n  - Sync API and implementation (not implemented yet)\n\n## Installation\n\nNPM: `npm install reactronic`\n\n## API (TypeScript)\n\n```typescript\n\n// Classes\n\nclass TxObject { } // transactional object\nclass RxObject { } // reactive object\n\n// Decorators \u0026 Operators\n\nfunction signal(boolean) // field only\nfunction signal(proto, prop) // field only\nfunction transaction(proto, prop, pd) // method only\nfunction reaction(proto, prop, pd) // method only\nfunction cache(proto, prop, pd) // method only\nfunction options(value: Partial\u003cReactivityOptions\u003e): F\u003cany\u003e\n\nfunction runNonReactive\u003cT\u003e(func: F\u003cT\u003e, ...args: any[]): T\nfunction runSensitive\u003cT\u003e(sensitivity: Sensitivity, func: F\u003cT\u003e, ...args: any[]): T\n\n// SnapshotOptions, ReactivityOptions, Kind, Reentrance, Indicator, LoggingOptions, ProfilingOptions\n\nexport type SnapshotOptions = {\n  readonly hint?: string\n  readonly isolation?: Isolation\n  readonly journal?: Journal\n  readonly logging?: Partial\u003cLoggingOptions\u003e\n  readonly token?: any\n}\n\ntype ReactivityOptions = {\n  readonly kind: Kind\n  readonly isolation: Isolation\n  readonly order: number\n  readonly noSideEffects: boolean\n  readonly signalArgs: boolean\n  readonly throttling: number // milliseconds, -1 is immediately, Number.MAX_SAFE_INTEGER is never\n  readonly reentrance: Reentrance\n  readonly journal: Journal | undefined\n  readonly indicator: Indicator | null\n  readonly logging?: Partial\u003cLoggingOptions\u003e\n}\n\nenum Kind {\n  plain = 0,\n  transaction = 1,\n  reaction = 2,\n  cache = 3\n}\n\nenum Reentrance {\n  preventWithError = 1, // fail with error if there is an existing call in progress (default)\n  waitAndRestart = 0, // wait for existing call to finish and then restart current one\n  cancelPrevious = -1, // cancel previous call in favor of recent one\n  cancelAndWaitPrevious = -2, // cancel previous call in favor of recent one (but wait until canceling is completed)\n  overwritePrevious = -2, // allow previous to complete, but overwrite it with ignoring any conflicts\n  runSideBySide = -3 // multiple simultaneous calls are allowed\n}\n\nclass Indicator {\n  readonly isBusy: boolean\n  readonly counter: number\n  readonly workers: ReadonlySet\u003cWorker\u003e\n  readonly busyDuration: number\n  abstract whenBusy(): Promise\u003cvoid\u003e\n  abstract whenIdle(): Promise\u003cvoid\u003e\n  static create(hint: string, activationDelay: number, deactivationDelay: number): Indicator\n}\n\ntype Worker = {\n  readonly id: number\n  readonly hint: string\n  isCanceled: boolean\n  isFinished: boolean\n  cancel(error?: Error, retryAfter?: Transaction): this\n  whenFinished(): Promise\u003cvoid\u003e\n}\n\ntype LoggingOptions = {\n  readonly off: boolean\n  readonly transaction: boolean\n  readonly operation: boolean\n  readonly step: boolean\n  readonly indicator: boolean\n  readonly read: boolean\n  readonly write: boolean\n  readonly change: boolean\n  readonly obsolete: boolean\n  readonly error: boolean\n  readonly warning: boolean\n  readonly gc: boolean\n}\n\ntype ProfilingOptions = {\n  repetitiveUsageWarningThreshold: number // default: 10 times\n  mainThreadBlockingWarningThreshold: number // default: 16.6 ms\n  asyncActionDurationWarningThreshold: number // default: 150 ms\n}\n\n// Transaction\n\ntype F\u003cT\u003e = (...args: any[]) =\u003e T\n\nclass Transaction implements Worker {\n  static readonly current: Transaction\n\n  readonly id: number\n  readonly hint: string\n\n  run\u003cT\u003e(func: F\u003cT\u003e, ...args: any[]): T\n  wrap\u003cT\u003e(func: F\u003cT\u003e): F\u003cT\u003e\n  apply(): void\n  seal(): this // a1.seal().whenFinished().then(fulfill, reject)\n  cancel(error?: Error, retryAfter?: Transaction): this\n  isCanceled: boolean\n  isFinished: boolean\n  whenFinished(): Promise\u003cvoid\u003e\n  join\u003cT\u003e(p: Promise\u003cT\u003e): Promise\u003cT\u003e\n\n  static create(options: SnapshotOptions | null): Transaction\n  static run\u003cT\u003e(options: SnapshotOptions | null, func: F\u003cT\u003e, ...args: any[]): T\n  static off\u003cT\u003e(func: F\u003cT\u003e, ...args: any[]): T\n\n  static isFrameOver(everyN: number, timeLimit: number): boolean\n  static requestNextFrame(sleepTime: number): Promise\u003cvoid\u003e\n  static isCanceled: boolean\n}\n\n// Reaction\n\nabstract class Reaction\u003cT\u003e {\n  readonly options: Options\n  readonly args: ReadonlyArray\u003cany\u003e\n  readonly value: T\n  readonly error: any\n  readonly stamp: number\n  readonly isReusable: boolean\n\n  configure(options: Partial\u003cOptions\u003e): Options\n  markObsolete(): boolean\n  pullLastResult(args?: any[]): T | undefined\n}\n\n// ReactiveSystem\n\nclass ReactiveSystem {\n  static why(short: boolean = false): string\n  static getMethodCache\u003cT\u003e(method: F\u003cT\u003e): Cache\u003cT\u003e\n  static configureCurrentReaction(options: Partial\u003cOptions\u003e): Options\n  static getRevisionOf(obj: any): number\n  static takeSnapshot\u003cT\u003e(obj: T): T\n  static dispose(obj: any): void\n  static reactivityAutoStartDisabled: boolean\n  static readonly isLogging: boolean\n  static readonly loggingOptions: LoggingOptions\n  static setLoggingMode(isOn: boolean, options?: LoggingOptions)\n  static setLoggingHint\u003cT extends object\u003e(obj: T, name: string | undefined): void\n  static getLoggingHint\u003cT extends object\u003e(obj: T): string | undefined\n  static setProfilingMode(isOn: boolean, options?: Partial\u003cProfilingOptions\u003e): void\n}\n\n```\n\n## Contribution\n\nBy contributing, you agree that your contributions will be\nautomatically licensed under the Apache 2.0 license (see LICENSE file).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnezaboodka%2Freactronic","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnezaboodka%2Freactronic","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnezaboodka%2Freactronic/lists"}