@dhmk/atom
Advanced tools
Comparing version 1.0.6 to 2.0.0
@@ -1,3 +0,30 @@ | ||
export * from "./atom"; | ||
export * from "./helpers"; | ||
export * from "./flow"; | ||
import { ValueAtom } from "./atoms/value"; | ||
import { ComputedAtom } from "./atoms/computed"; | ||
import { EffectAtom } from "./atoms/effect"; | ||
import { runtime } from "./runtime"; | ||
import { AtomOptions, EffectAtomOptions } from "./types"; | ||
import observable from "./observable"; | ||
import observableObject, { as } from "./observable/object"; | ||
import observableArray from "./observable/array"; | ||
type EffectState = { | ||
(): void; | ||
isInitial: boolean; | ||
invalidate(): void; | ||
}; | ||
declare function observe(fn: (state: EffectState) => void, opts?: EffectAtomOptions): EffectState; | ||
type Atom<T> = { | ||
get(): T; | ||
}; | ||
type WritableAtom<T> = Atom<T> & { | ||
set(x: T): void; | ||
}; | ||
type AtomOptions_<T> = AtomOptions<T> & Partial<{ | ||
set(setter: (x: T) => void): (x: T) => void; | ||
}>; | ||
type ComputedOptions_<T> = AtomOptions<T>; | ||
type Getter<T> = () => T; | ||
declare function atom<T>(fn: () => T, opts?: ComputedOptions_<T>): Atom<T> & Getter<T>; | ||
declare function atom<T>(value: T, opts?: AtomOptions_<T>): WritableAtom<T> & Getter<T>; | ||
declare const act: <T>(fn: () => T) => T; | ||
declare const untracked: <T>(fn: () => T) => T; | ||
export { ValueAtom, ComputedAtom, EffectAtom, atom, act, untracked, observe, observable, observableObject, observableArray, as, runtime, }; |
@@ -1,3 +0,37 @@ | ||
export * from "./atom"; | ||
export * from "./helpers"; | ||
export * from "./flow"; | ||
import { ValueAtom } from "./atoms/value"; | ||
import { ComputedAtom } from "./atoms/computed"; | ||
import { EffectAtom } from "./atoms/effect"; | ||
import { runtime } from "./runtime"; | ||
import { AtomState } from "./types"; | ||
import observable from "./observable"; | ||
import observableObject, { as } from "./observable/object"; | ||
import observableArray from "./observable/array"; | ||
function observe(fn, opts) { | ||
var ectrl = function () { return ea.dispose(); }; | ||
ectrl.isInitial = true; | ||
ectrl.invalidate = function () { return ea.invalidate(AtomState.Stale, false); }; | ||
var efn = function () { | ||
fn(ectrl); | ||
ectrl.isInitial = false; | ||
}; | ||
var ea = new EffectAtom(efn, opts); | ||
var onBO = opts === null || opts === void 0 ? void 0 : opts.onBecomeObserved; | ||
if (onBO) | ||
runtime.addEffect({ actualize: onBO }); | ||
ea.start(); | ||
return ectrl; | ||
} | ||
function atom(x, opts) { | ||
var _a; | ||
var a = typeof x === "function" | ||
? new ComputedAtom(x, opts) | ||
: new ValueAtom(x, opts); | ||
var self = a.get.bind(a); | ||
self.set = "set" in a ? ((_a = opts === null || opts === void 0 ? void 0 : opts.set) !== null && _a !== void 0 ? _a : (function (x) { return x; }))(a.set.bind(a)) : undefined; | ||
self.get = self.toString = self.toJSON = self.valueOf = self; | ||
return self; | ||
} | ||
var act = runtime.act; | ||
var untracked = act; | ||
export { ValueAtom, ComputedAtom, EffectAtom, atom, act, untracked, observe, observable, observableObject, observableArray, as, runtime, // debug | ||
}; |
@@ -1,3 +0,30 @@ | ||
export * from "./atom"; | ||
export * from "./helpers"; | ||
export * from "./flow"; | ||
import { ValueAtom } from "./atoms/value"; | ||
import { ComputedAtom } from "./atoms/computed"; | ||
import { EffectAtom } from "./atoms/effect"; | ||
import { runtime } from "./runtime"; | ||
import { AtomOptions, EffectAtomOptions } from "./types"; | ||
import observable from "./observable"; | ||
import observableObject, { as } from "./observable/object"; | ||
import observableArray from "./observable/array"; | ||
type EffectState = { | ||
(): void; | ||
isInitial: boolean; | ||
invalidate(): void; | ||
}; | ||
declare function observe(fn: (state: EffectState) => void, opts?: EffectAtomOptions): EffectState; | ||
type Atom<T> = { | ||
get(): T; | ||
}; | ||
type WritableAtom<T> = Atom<T> & { | ||
set(x: T): void; | ||
}; | ||
type AtomOptions_<T> = AtomOptions<T> & Partial<{ | ||
set(setter: (x: T) => void): (x: T) => void; | ||
}>; | ||
type ComputedOptions_<T> = AtomOptions<T>; | ||
type Getter<T> = () => T; | ||
declare function atom<T>(fn: () => T, opts?: ComputedOptions_<T>): Atom<T> & Getter<T>; | ||
declare function atom<T>(value: T, opts?: AtomOptions_<T>): WritableAtom<T> & Getter<T>; | ||
declare const act: <T>(fn: () => T) => T; | ||
declare const untracked: <T>(fn: () => T) => T; | ||
export { ValueAtom, ComputedAtom, EffectAtom, atom, act, untracked, observe, observable, observableObject, observableArray, as, runtime, }; |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
@@ -9,8 +13,65 @@ if (k2 === undefined) k2 = k; | ||
})); | ||
var __exportStar = (this && this.__exportStar) || function(m, exports) { | ||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
__exportStar(require("./atom"), exports); | ||
__exportStar(require("./helpers"), exports); | ||
__exportStar(require("./flow"), exports); | ||
exports.runtime = exports.as = exports.observableArray = exports.observableObject = exports.observable = exports.observe = exports.untracked = exports.act = exports.atom = exports.EffectAtom = exports.ComputedAtom = exports.ValueAtom = void 0; | ||
var value_1 = require("./atoms/value"); | ||
Object.defineProperty(exports, "ValueAtom", { enumerable: true, get: function () { return value_1.ValueAtom; } }); | ||
var computed_1 = require("./atoms/computed"); | ||
Object.defineProperty(exports, "ComputedAtom", { enumerable: true, get: function () { return computed_1.ComputedAtom; } }); | ||
var effect_1 = require("./atoms/effect"); | ||
Object.defineProperty(exports, "EffectAtom", { enumerable: true, get: function () { return effect_1.EffectAtom; } }); | ||
var runtime_1 = require("./runtime"); | ||
Object.defineProperty(exports, "runtime", { enumerable: true, get: function () { return runtime_1.runtime; } }); | ||
var types_1 = require("./types"); | ||
var observable_1 = __importDefault(require("./observable")); | ||
exports.observable = observable_1.default; | ||
var object_1 = __importStar(require("./observable/object")); | ||
exports.observableObject = object_1.default; | ||
Object.defineProperty(exports, "as", { enumerable: true, get: function () { return object_1.as; } }); | ||
var array_1 = __importDefault(require("./observable/array")); | ||
exports.observableArray = array_1.default; | ||
function observe(fn, opts) { | ||
var ectrl = function () { return ea.dispose(); }; | ||
ectrl.isInitial = true; | ||
ectrl.invalidate = function () { return ea.invalidate(types_1.AtomState.Stale, false); }; | ||
var efn = function () { | ||
fn(ectrl); | ||
ectrl.isInitial = false; | ||
}; | ||
var ea = new effect_1.EffectAtom(efn, opts); | ||
var onBO = opts === null || opts === void 0 ? void 0 : opts.onBecomeObserved; | ||
if (onBO) | ||
runtime_1.runtime.addEffect({ actualize: onBO }); | ||
ea.start(); | ||
return ectrl; | ||
} | ||
exports.observe = observe; | ||
function atom(x, opts) { | ||
var _a; | ||
var a = typeof x === "function" | ||
? new computed_1.ComputedAtom(x, opts) | ||
: new value_1.ValueAtom(x, opts); | ||
var self = a.get.bind(a); | ||
self.set = "set" in a ? ((_a = opts === null || opts === void 0 ? void 0 : opts.set) !== null && _a !== void 0 ? _a : (function (x) { return x; }))(a.set.bind(a)) : undefined; | ||
self.get = self.toString = self.toJSON = self.valueOf = self; | ||
return self; | ||
} | ||
exports.atom = atom; | ||
var act = runtime_1.runtime.act; | ||
exports.act = act; | ||
var untracked = act; | ||
exports.untracked = untracked; |
{ | ||
"name": "@dhmk/atom", | ||
"version": "1.0.6", | ||
"version": "2.0.0", | ||
"description": "Lightweight mobx-like observable values, computed values and side-effects", | ||
@@ -25,2 +25,8 @@ "keywords": [ | ||
], | ||
"devDependencies": { | ||
"@types/jest": "^26.0.23", | ||
"jest": "^26.6.3", | ||
"ts-jest": "^26.5.6", | ||
"typescript": "^4.2.4" | ||
}, | ||
"scripts": { | ||
@@ -33,12 +39,3 @@ "preversion": "yarn test && yarn build", | ||
"test": "yarn clean && jest" | ||
}, | ||
"devDependencies": { | ||
"@types/jest": "^26.0.23", | ||
"jest": "^26.6.3", | ||
"ts-jest": "^26.5.6", | ||
"typescript": "^4.2.4" | ||
}, | ||
"dependencies": { | ||
"@dhmk/utils": "^2.0.0" | ||
} | ||
} | ||
} |
147
README.md
# @dhmk-atom | ||
Mobx-like observable atoms, computeds and observers. | ||
MobX-like observable atoms, computeds and observers. | ||
Install: `npm install @dhmk/atom` | ||
## Atom types | ||
## Example | ||
```ts | ||
type Atom<T> = { | ||
(): T; | ||
}; | ||
``` | ||
import { observable, observe, act } from "@dhmk-atom"; | ||
```ts | ||
type WritableAtom<T> = { | ||
(): T; | ||
set(value: T): boolean; // true - if `value` differs from previous one | ||
}; | ||
``` | ||
const x = observable({ | ||
id: 123, | ||
get computedProp() { | ||
return this.id.toString(); | ||
}, | ||
}); | ||
```ts | ||
type AtomOptions = { | ||
eq: (oldValue, newValue) => boolean; | ||
onBecomeObserved: () => void; | ||
onBecomeUnobserved: () => void; | ||
setter: (originalSetter: Setter<T>) => Setter<T>; | ||
}; | ||
const dispose = observe(() => console.log(x.computedProp)); | ||
type Setter<T> = (value: T) => ValueChanged | ValueNotChanged; | ||
act(() => (x.id = 456)); | ||
type ValueChanged = true; | ||
type ValueNotChanged = false; | ||
dispose(); | ||
``` | ||
## API | ||
### `atom(value: T, opts?: AtomOptions): WritableAtom<T>` | ||
Creates a value atom which is very similar to MobX `observable.box(value, { deep: false })`. The only difference is that the `.get()` is replaced by calling `()` directly. | ||
Creates a value atom which is similar to MobX [observable.box(value, { deep: false })](https://mobx.js.org/api.html#observablebox). | ||
### `atom(fn: () => T, opts?: AtomOptions): Atom<T>` | ||
```ts | ||
type AtomOptions = { | ||
equals?: (next: T, prev: T) => boolean; | ||
onBecomeObserved?: () => void; | ||
onBecomeUnobserved?: () => void; | ||
set?: (setter: (x: T) => void) => (x: T) => void; | ||
}; | ||
Creates a computed atom which is like Mobx `computed(fn)`. | ||
type WritableAtom<T> = { | ||
(): T; | ||
get(): T; | ||
set(x: T): void; | ||
}; | ||
``` | ||
## Observer types | ||
### `atom(fn: () => T, opts?: ComputedAtomOptions): Atom<T>` | ||
Creates a computed atom which is similar to MobX [computed](https://mobx.js.org/api.html#computed). | ||
```ts | ||
type Observer = { | ||
(): void; // dispose | ||
invalidate(forceThroughBatches = false): void; | ||
readonly isInitial: boolean; | ||
readonly isDisposed: boolean; | ||
type ComputedAtomOptions = { | ||
equals?: (next: T, prev: T) => boolean; | ||
onBecomeObserved?: () => void; | ||
onBecomeUnobserved?: () => void; | ||
}; | ||
``` | ||
```ts | ||
type ObserverOptions = { | ||
attachToParent: boolean = true; | ||
checkStale: boolean = true; | ||
scheduler: (run: Function) => void; | ||
type ComputedAtom<T> = { | ||
(): T; | ||
get(): T; | ||
}; | ||
``` | ||
### `observe(fn: (self: Observer) => void, opts?: ObserverOptions): Observer` | ||
### `observable(x)` | ||
Creates an observer which is like Mobx `autorun(fn)`. Whenever an atom which was read during `fn` execution changes, the observer schedules `fn` for execution once again. | ||
Creates observable object or array. See also `observableObject`, `observableArray`, `as`. | ||
#### `Observer.invalidate(force?)` | ||
### `observe(fn: (self: Observer) => void, opts?: ObserverOptions): Observer` | ||
Schedules `fn` for execution even if no tracked atoms were changed. If `force` is true also ignores any current transactions. | ||
Similar to MobX [autorun](https://mobx.js.org/api.html#autorun). | ||
#### `ObserverOptions.attachToParent` | ||
```ts | ||
type ObserverOptions = { | ||
scheduler?: (run: Function) => void; | ||
onBecomeObserved?: () => void; | ||
onBecomeUnobserved?: () => void; | ||
}; | ||
When true created observer will be tracked by parent observer if exists. Whenever the parent observer `fn` re-executes it will dispose this tracked child observer. If there is no parent observer you must dispose created observer manually. | ||
type Observer = { | ||
// dispose | ||
(): void; | ||
When false, you must dispose created observer manually. | ||
// schedule observer for execution even if no tracked atoms were changed | ||
invalidate(): void; | ||
#### `ObserverOptions.checkStale` | ||
readonly isInitial: boolean; | ||
}; | ||
``` | ||
When true throws an error if no atoms were read during `fn` execution. Because in this case observer will become stale and will not call its `fn` until you `invalidate` it manually. | ||
### `act(fn: () => T): T` | ||
## Transactions (batches) | ||
MobX [runInAction](https://mobx.js.org/api.html#runinaction). | ||
Transactions are similar to MobX transactions. During a transaction no observers are run automatically (though you can run one by calling `observer.invalidate(true)`). Also, no atoms are tracked (`untracked(fn)` is applied). | ||
### `untracked(fn: () => T): T` | ||
Runs `fn` without tracking any atoms which are read during its execution. Returns `fn` result. Doesn't apply transaction. | ||
MobX [untracked](https://mobx.js.org/api.html#untracked). | ||
### `runInAction(fn: () => T): T` | ||
### `as(x: { get, set? })` | ||
Runs `fn` in transaction. Returns `fn` result. Also applies `untracked`. | ||
Instructs `observableObject` to initialize property as given object instead of default behavior. | ||
### `runInFlow(flow)` | ||
### `observableObject(x)` | ||
Runs `flow` in transaction. Returns its result. See [@dhmk/utils](https://github.com/dhmk083/dhmk-utils/blob/d3bea84901abd0836dcc9e72b1b5a800a29577c9/src/fn.ts#L103) for more info about flow. | ||
```ts | ||
observableObject({ | ||
id: 123, | ||
get computedProp() { | ||
return this.id.toString(); | ||
}, | ||
withOptions: as(atom("abc", { onBecomeObserved() {} })), | ||
}); | ||
``` | ||
### `atTransactionEnd(fn)` | ||
### `observableArray(x)` | ||
Runs `fn` at the end of the outermost transaction or immediately if is not in transaction. | ||
### `ValueAtom` | ||
## Helpers | ||
### `ComputedAtom` | ||
### `keepAlive(computed: Atom<T>): Atom<T> & { dispose() }` | ||
Similar to MobX, if a computed atom isn't observed by anyone, its value is recomputed on every access. This function is a shorcut to `observe(computed)`. | ||
### `objectAtom()` | ||
### `arrayAtom()` | ||
### `mapAtom()` | ||
### `setAtom()` | ||
### `asyncAtom()` | ||
### `debouncedEvents()` | ||
### `EffectAtom` |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
71144
0
46
1946
121
1
- Removed@dhmk/utils@^2.0.0
- Removed@dhmk/utils@2.4.2(transitive)