Skip to content

Commit

Permalink
feat: Changed API - renamed Action to Signal
Browse files Browse the repository at this point in the history
  • Loading branch information
mnasyrov committed Nov 1, 2023
1 parent c0f1ee9 commit dfc0f43
Show file tree
Hide file tree
Showing 12 changed files with 91 additions and 91 deletions.
2 changes: 1 addition & 1 deletion src-temp/effect-monitor/effect.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
} from 'rxjs';
import { switchMap, take, toArray } from 'rxjs/operators';

import { createAction } from '../../src/core/action';
import { createAction } from '../../src/core/signal';

import { createEffect } from './effect';
import { GLOBAL_EFFECT_UNHANDLED_ERROR$ } from './effectController';
Expand Down
10 changes: 5 additions & 5 deletions src-temp/effect-monitor/effect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
Unsubscribable,
} from 'rxjs';

import { Action } from '../../src/core/action';
import { Signal } from '../../src/core/signal';
import { Controller } from '../../src/mvc/controller';

import { createEffectController } from './effectController';
Expand All @@ -35,7 +35,7 @@ const DEFAULT_MERGE_MAP_PIPELINE: EffectPipeline<any, any> = (eventProject) =>
mergeMap(eventProject);

/**
* Effect encapsulates a handler for Action or Observable.
* Effect encapsulates a handler for Signal or Observable.
*
* It provides the state of execution results, which can be used to construct
* a graph of business logic.
Expand All @@ -46,7 +46,7 @@ const DEFAULT_MERGE_MAP_PIPELINE: EffectPipeline<any, any> = (eventProject) =>
export type Effect<Event, Result = void, ErrorType = Error> = Controller<
EffectState<Event, Result, ErrorType> & {
handle: (
source: Action<Event> | Observable<Event> | Query<Event>,
source: Signal<Event> | Observable<Event> | Query<Event>,
) => Unsubscribable;
}
>;
Expand Down Expand Up @@ -105,7 +105,7 @@ export function createEffect<Event = void, Result = void, ErrorType = Error>(
...controller.state,

handle(
source: Observable<Event> | Action<Event> | Query<Event>,
source: Observable<Event> | Signal<Event> | Query<Event>,
): Subscription {
const observable = getSourceObservable(source);

Expand All @@ -125,7 +125,7 @@ export function createEffect<Event = void, Result = void, ErrorType = Error>(
}

function getSourceObservable<T>(
source: Observable<T> | Action<T> | Query<T>,
source: Observable<T> | Signal<T> | Query<T>,
): Observable<T> {
const type = typeof source;

Expand Down
16 changes: 8 additions & 8 deletions src-temp/effect-monitor/effectController.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { action, isActionObserved } from '../../src/core/action';
import { compute } from '../../src/core/compute';
import { createScope } from '../../src/core/scope';
import { isSignalObserved, signal } from '../../src/core/signal';
import { Controller } from '../../src/mvc/controller';

import {
Expand All @@ -11,15 +11,15 @@ import {
} from './effectState';

const GLOBAL_EFFECT_UNHANDLED_ERROR_EMITTER =
action<EffectError<unknown, unknown>>();
signal<EffectError<unknown, unknown>>();

export const GLOBAL_EFFECT_UNHANDLED_ERRORS =
GLOBAL_EFFECT_UNHANDLED_ERROR_EMITTER;

function emitGlobalUnhandledError(
effectError: EffectError<unknown, unknown>,
): void {
if (isActionObserved(GLOBAL_EFFECT_UNHANDLED_ERROR_EMITTER)) {
if (isSignalObserved(GLOBAL_EFFECT_UNHANDLED_ERROR_EMITTER)) {
GLOBAL_EFFECT_UNHANDLED_ERROR_EMITTER(effectError);
} else {
console.error('Uncaught error in EffectMonitor', effectError);
Expand All @@ -45,10 +45,10 @@ export function createEffectController<
>(): EffectController<Event, Result, ErrorType> {
const scope = createScope();

const done = scope.action<EffectResult<Event, Result>>();
const result = scope.action<Result>();
const error = scope.action<EffectError<Event, ErrorType>>();
const final = scope.action<EffectNotification<Event, Result, ErrorType>>();
const done = scope.signal<EffectResult<Event, Result>>();
const result = scope.signal<Result>();
const error = scope.signal<EffectError<Event, ErrorType>>();
const final = scope.signal<EffectNotification<Event, Result, ErrorType>>();
const pendingCount = scope.atom(0);

return {
Expand Down Expand Up @@ -76,7 +76,7 @@ export function createEffectController<
pendingCount.update(decreaseCount);
}

if (isActionObserved(error) || isActionObserved(final)) {
if (isSignalObserved(error) || isSignalObserved(final)) {
error(effectError);
final({ type: 'error', ...effectError });
} else {
Expand Down
10 changes: 5 additions & 5 deletions src-temp/effect-monitor/effectState.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Action } from '../../src/core/action';
import { Atom } from '../../src/core/common';
import { Signal } from '../../src/core/signal';

export type EffectResult<Event, Value> = Readonly<{
event: Event;
Expand Down Expand Up @@ -31,17 +31,17 @@ export type EffectNotification<Event, Result, ErrorType> = Readonly<
*/
export type EffectState<Event, Result = void, ErrorType = Error> = Readonly<{
/** Provides a result of successful execution of the handler */
result: Action<Result>;
result: Signal<Result>;

/** Provides a source event and a result of successful execution of the handler */
done: Action<EffectResult<Event, Result>>;
done: Signal<EffectResult<Event, Result>>;

/** Provides an error emitter by a source (`event` is `undefined`)
* or by the handler (`event` is not `undefined`) */
error: Action<EffectError<Event, ErrorType>>;
error: Signal<EffectError<Event, ErrorType>>;

/** Provides a notification after execution of the handler for both success or error result */
final: Action<EffectNotification<Event, Result, ErrorType>>;
final: Signal<EffectNotification<Event, Result, ErrorType>>;

/** Provides `true` if there is any execution of the handler in progress */
pending: Atom<boolean>;
Expand Down
4 changes: 2 additions & 2 deletions src/core/_public.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export type { Action, ActionOptions } from './action';
export { action, isAction, destroyAction, isActionObserved } from './action';
export type { Signal, SignalOptions } from './signal';
export { signal, isSignal, destroySignal, isSignalObserved } from './signal';

export type { Atom, ValueEqualityFn } from './common';
export { isAtom, defaultEquals, objectEquals } from './common';
Expand Down
8 changes: 4 additions & 4 deletions src/core/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,18 +134,18 @@ export type AtomEffectNode = ReactiveNode &
notify: () => void;
}>;

export type ActionNode<T> = ReactiveNode &
export type SignalNode<T> = ReactiveNode &
Readonly<{
isDestroyed: boolean;
isObserved: () => boolean;

emit: (value: T) => void;
subscribe: (effectRef: WeakRef<ActionEffectNode<T>>) => void;
subscribe: (effectRef: WeakRef<SignalEffectNode<T>>) => void;
}>;

export type ActionEffectNode<T> = ReactiveNode &
export type SignalEffectNode<T> = ReactiveNode &
Readonly<{
ref: WeakRef<ActionEffectNode<T>>;
ref: WeakRef<SignalEffectNode<T>>;
isDestroyed: boolean;

notify: (value: T) => void;
Expand Down
10 changes: 5 additions & 5 deletions src/core/effect.test.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { flushMicrotasks } from '../test/testUtils';

import { action } from './action';
import { atom } from './atom';
import { compute } from './compute';
import { effect, syncEffect } from './effect';
import { signal } from './signal';

describe('effect()', () => {
it('should subscribe to an action', async () => {
const emitter = action<number>();
it('should subscribe to a signal', async () => {
const emitter = signal<number>();

let result = 0;
const fx = effect(emitter, (value) => (result = value));
Expand Down Expand Up @@ -90,8 +90,8 @@ describe('effect()', () => {
});

describe('syncEffect()', () => {
it('should subscribe to an action', () => {
const emitter = action<number>();
it('should subscribe to a signal', () => {
const emitter = signal<number>();

let result = 0;
const fx = syncEffect(emitter, (value) => (result = value));
Expand Down
34 changes: 17 additions & 17 deletions src/core/effect.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { TaskScheduler } from '../utils/schedulers';

import { Action, getActionNode, isAction } from './action';
import { ActionEffect } from './actionEffect';
import { createAtomEffect } from './atomEffect';
import { Atom, isAtom } from './common';
import { ENERGY_RUNTIME } from './runtime';
import { getSignalNode, isSignal, Signal } from './signal';
import { SignalEffect } from './signalEffect';

/**
* An effect can, optionally, register a cleanup function. If registered, the cleanup is executed
Expand Down Expand Up @@ -38,7 +38,7 @@ TODO
*/

export interface EffectFn {
<T>(source: Action<T>, callback: ValueCallbackFn<T>): EffectSubscription;
<T>(source: Signal<T>, callback: ValueCallbackFn<T>): EffectSubscription;
<T>(
source: Atom<T>,
callback: ValueCallbackFn<T>,
Expand All @@ -49,13 +49,13 @@ export interface EffectFn {

export const effect: EffectFn = <
T,
Source extends Action<T> | Atom<T> | SideEffectFn,
Callback extends Source extends Action<T>
Source extends Signal<T> | Atom<T> | SideEffectFn,
Callback extends Source extends Signal<T>
? ValueCallbackFn<T>
: Source extends Atom<T>
? ValueCallbackFn<T>
: never,
ErrorCallback extends Source extends Action<T>
ErrorCallback extends Source extends Signal<T>
? never
: Source extends Atom<T>
? ErrorCallbackFn
Expand All @@ -75,13 +75,13 @@ export const effect: EffectFn = <

export const syncEffect: EffectFn = <
T,
Source extends Action<T> | Atom<T> | SideEffectFn,
Callback extends Source extends Action<T>
Source extends Signal<T> | Atom<T> | SideEffectFn,
Callback extends Source extends Signal<T>
? ValueCallbackFn<T>
: Source extends Atom<T>
? ValueCallbackFn<T>
: never,
ErrorCallback extends Source extends Action<T>
ErrorCallback extends Source extends Signal<T>
? never
: Source extends Atom<T>
? ErrorCallbackFn
Expand All @@ -101,13 +101,13 @@ export const syncEffect: EffectFn = <

function effectFactory<
T,
Source extends Action<T> | Atom<T> | SideEffectFn,
Callback extends Source extends Action<T>
Source extends Signal<T> | Atom<T> | SideEffectFn,
Callback extends Source extends Signal<T>
? ValueCallbackFn<T>
: Source extends Atom<T>
? ValueCallbackFn<T>
: never,
ErrorCallback extends Source extends Action<T>
ErrorCallback extends Source extends Signal<T>
? never
: Source extends Atom<T>
? ErrorCallbackFn
Expand All @@ -118,14 +118,14 @@ function effectFactory<
callback?: Callback,
errorCallback?: ErrorCallback,
): EffectSubscription {
if (isAction<T>(source)) {
if (isSignal<T>(source)) {
if (!callback) throw new Error('callback is missed');
const node = getActionNode<T>(source);
const node = getSignalNode<T>(source);

const actionEffect = new ActionEffect<T>(scheduler, callback);
node.subscribe(actionEffect.ref);
const signalEffect = new SignalEffect<T>(scheduler, callback);
node.subscribe(signalEffect.ref);

return { destroy: () => actionEffect.destroy() };
return { destroy: () => signalEffect.destroy() };
}

let sideEffectFn: SideEffectFn;
Expand Down
12 changes: 6 additions & 6 deletions src/core/scope.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { action, destroyAction } from './action';
import { atom } from './atom';
import { effect, EffectFn, syncEffect } from './effect';
import { destroySignal, signal } from './signal';

export interface Unsubscribable {
unsubscribe(): void;
Expand All @@ -24,8 +24,8 @@ export type Scope = Readonly<

add: <T extends Unsubscribable | Destroyable>(resource: T) => T;

action: typeof action;
atom: typeof atom;
signal: typeof signal;
effect: EffectFn;
syncEffect: EffectFn;
}
Expand Down Expand Up @@ -101,9 +101,9 @@ class ScopeImpl implements Scope {
}
}

action<T>(...args: Parameters<typeof action<T>>) {
const emitter = action<T>(...args);
this.onDestroy(() => destroyAction(emitter));
signal<T>(...args: Parameters<typeof signal<T>>) {
const emitter = signal<T>(...args);
this.onDestroy(() => destroySignal(emitter));
return emitter;
}

Expand Down Expand Up @@ -132,7 +132,7 @@ export function createScope(): Scope {

add: scope.add.bind(scope),

action: scope.action.bind(scope),
signal: scope.signal.bind(scope),
atom: scope.atom.bind(scope),
effect: scope.effect.bind(scope),
syncEffect: scope.syncEffect.bind(scope),
Expand Down
10 changes: 5 additions & 5 deletions src/core/action.test.ts → src/core/signal.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { flushMicrotasks } from '../test/testUtils';

import { action } from './action';
import { effect } from './effect';
import { signal } from './signal';

describe('action', () => {
it('should emit the event', async () => {
const a = action<number>();
describe('signal()', () => {
it('should return an event emitter', async () => {
const a = signal<number>();

let result;
effect(a, (value) => (result = value));
Expand All @@ -16,7 +16,7 @@ describe('action', () => {
});

it('should use void type and undefined value if a generic type is not specified', async () => {
const a = action();
const a = signal();

let count = 0;
effect(a, () => count++);
Expand Down
Loading

0 comments on commit dfc0f43

Please sign in to comment.