nrgy
Version:
The library for reactive programming using efficient computing and MVC/MVVM patterns
234 lines (222 loc) • 5.73 kB
JavaScript
import {
BaseScope,
RUNTIME,
atom,
compute,
createAtomFromFunction,
defaultEquals,
destroySignal,
effect,
getAtomNode,
signal,
syncEffect
} from "./chunk-6EESSQRU.js";
// src/core/scope/createScope.ts
function createScope() {
const scope = new BaseScope();
return {
onDestroy: scope.onDestroy.bind(scope),
add: scope.add.bind(scope),
destroy: scope.destroy.bind(scope),
createScope: () => {
return scope.add(createScope());
},
signal: (...args) => {
const emitter = signal(...args);
scope.onDestroy(() => destroySignal(emitter));
return emitter;
},
atom: (...args) => {
return scope.add(atom(...args));
},
effect: (...args) => {
return scope.add(effect(...args));
},
syncEffect: (...args) => {
return scope.add(syncEffect(...args));
}
};
}
// src/core/utils/atomSubject.ts
function createAtomSubject(initialValue, options) {
let readonlyAtom = void 0;
const state = atom(
{
type: 0 /* value */,
value: initialValue
},
{
name: options == null ? void 0 : options.name,
onDestroy: options == null ? void 0 : options.onDestroy
}
);
const result = compute(
() => {
const current = state();
switch (current.type) {
case 0 /* value */:
return current.value;
case 1 /* error */:
throw current.error;
}
},
{
equal: options == null ? void 0 : options.equal
}
);
const onDestroyed = state.onDestroyed;
const destroy = () => state.destroy();
const node = getAtomNode(result);
let observableAtom;
const asReadonly = () => {
if (readonlyAtom === void 0) {
readonlyAtom = createAtomFromFunction(node, () => result());
}
return readonlyAtom;
};
const resultAtom = createAtomFromFunction(node, () => result(), {
next: (value) => state.set({ type: 0 /* value */, value }),
error: (error) => state.set({ type: 1 /* error */, error }),
onDestroyed,
destroy,
asDestroyable: () => {
if (!observableAtom) {
const node2 = getAtomNode(result);
observableAtom = createAtomFromFunction(node2, () => result(), {
onDestroyed,
destroy,
asReadonly
});
}
return observableAtom;
},
asReadonly
});
return resultAtom;
}
// src/core/utils/batch.ts
function batch(action) {
RUNTIME.batch(action);
}
// src/core/utils/keepLastValue.ts
function keepLastValue(source, initialValue) {
const scope = new BaseScope();
const subject = createAtomSubject(initialValue, {
onDestroy: scope.destroy
});
const sub = scope.add(syncEffect(source, subject.next));
scope.add(syncEffect(sub.onError, subject.error));
scope.add(syncEffect(sub.onDestroy, subject.destroy));
return subject.asDestroyable();
}
// src/core/utils/mapAtom.ts
function mapAtom(source, computation, options) {
return compute(() => computation(source()), options);
}
// src/core/utils/mergeAtoms.ts
function mergeAtoms(sources, computation, options) {
return compute(() => {
const values = sources.map((source) => source());
return computation(...values);
}, options);
}
// src/core/utils/mixSignals.ts
function mixSignals(sources, options) {
let subscriptionList;
function subscribeSources() {
if (subscriptionList === void 0) {
for (const source of sources) {
const fx = effect(source, resultSignal, { sync: options == null ? void 0 : options.sync });
subscriptionList = { subscription: fx, next: subscriptionList };
}
}
}
function unsubscribeSources() {
for (let item = subscriptionList; item; item = item.next) {
item.subscription.destroy();
}
subscriptionList = void 0;
}
const resultSignal = signal({
...options,
onSubscribe: () => {
var _a;
subscribeSources();
(_a = options == null ? void 0 : options.onSubscribe) == null ? void 0 : _a.call(options);
},
onUnsubscribe: (isEmpty) => {
var _a;
if (isEmpty) {
unsubscribeSources();
}
(_a = options == null ? void 0 : options.onUnsubscribe) == null ? void 0 : _a.call(options, isEmpty);
},
onDestroy: () => {
var _a;
unsubscribeSources();
(_a = options == null ? void 0 : options.onDestroy) == null ? void 0 : _a.call(options);
}
});
return resultSignal;
}
// src/core/utils/objectEquals.ts
var hasOwnProperty = Object.prototype.hasOwnProperty;
var objectEquals = (objA, objB) => {
if (objA === objB) {
return true;
}
const keysA = Object.keys(objA);
const keysB = Object.keys(objB);
if (keysA.length !== keysB.length) {
return false;
}
for (let i = 0; i < keysA.length; i++) {
const key = keysA[i];
if (!hasOwnProperty.call(objB, key) || !defaultEquals(objA[key], objB[key])) {
return false;
}
}
return true;
};
// src/core/utils/runEffects.ts
function runEffects() {
RUNTIME.asyncScheduler.execute();
}
// src/core/utils/signalChanges.ts
function signalChanges(source, options) {
const scope = new BaseScope();
if (options == null ? void 0 : options.onDestroy) {
scope.onDestroy(options.onDestroy);
}
const s = signal({
...options,
onDestroy: () => scope.destroy()
});
let first = true;
scope.add(
effect(
source,
(value) => {
if (first) {
first = false;
} else {
s(value);
}
},
{ sync: options == null ? void 0 : options.sync }
)
);
return s;
}
export {
createScope,
createAtomSubject,
batch,
keepLastValue,
mapAtom,
mergeAtoms,
mixSignals,
objectEquals,
runEffects,
signalChanges
};