Skip to content

Commit

Permalink
chore: bump to 3.5.19
Browse files Browse the repository at this point in the history
  • Loading branch information
fantasticsoul committed Dec 24, 2023
1 parent d51fd26 commit c59a8ba
Show file tree
Hide file tree
Showing 13 changed files with 191 additions and 72 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "helux",
"version": "3.5.17",
"version": "3.5.19",
"description": "A state library core that integrates atom, signal, collection dep, derive and watch, it supports all react like frameworks( including react 18 ).",
"keywords": [],
"author": {
Expand Down
4 changes: 3 additions & 1 deletion packages/helux-core/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { addMiddleware } from './factory/common/middleware';
import { addPlugin } from './factory/common/plugin';
import { emit, on } from './factory/common/userBus';
import { action } from './factory/createAction';
import { derive, deriveDict } from './factory/createDerived';
import { defineDeriveFnItem, defineDeriveTask, derive, deriveDict } from './factory/createDerived';
import { mutate, mutateDict, runMutate, runMutateTask } from './factory/createMutate';
import { atom, atomx, share, sharex } from './factory/createShared';
import { sync, syncer } from './factory/createSync';
Expand Down Expand Up @@ -47,6 +47,8 @@ export {
// derive api
derive,
deriveDict,
defineDeriveTask,
defineDeriveFnItem,
runDerive,
runDeriveTask,
// watch api
Expand Down
2 changes: 1 addition & 1 deletion packages/helux-core/src/consts/user.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { VER as limuVer } from 'limu';

export const VER = '3.5.18';
export const VER = '3.5.19';

export const LIMU_VER = limuVer;

Expand Down
17 changes: 10 additions & 7 deletions packages/helux-core/src/factory/common/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,18 @@ export function emitShareCreated(internal: TInternal) {

export function emitPluginEvent(internal: TInternal, evName: string, data: Dict) {
const { bus } = getRootCtx();
if (bus.canEmit(evName)) {
const { sharedKey, moduleName } = internal;
bus.emit(evName, { moduleName, sharedKey, data });
return;
if (!bus.canEmit(evName)) {
return false;
}
const { sharedKey, moduleName } = internal;
bus.emit(evName, { moduleName, sharedKey, data });
return true;
}

export function emitErr(internal: TInternal, err: Error) {
// 未安装错误捕捉插件时,提示作者出现错误的位置
if (evName === ON_ERROR_OCCURED) {
console.warn('found uncaught internal error, sugguest write a plugin to handle this error');
console.error(data.err);
if (!emitPluginEvent(internal, EVENT_NAME.ON_ERROR_OCCURED, { err })) {
console.warn('found uncaught error, sugguest add a plugin to handle this error');
console.error(err);
}
}
8 changes: 4 additions & 4 deletions packages/helux-core/src/factory/common/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@ export function tryGetLoc(moduleName: string, endCutIdx = 8) {
try {
throw new Error('loc');
} catch (err: any) {
const arr = err.stack.split("\n");
const arr: string[] = err.stack.split('\n');
const item1 = arr[1] || '';
if (item1.includes('webpack-internal') || item1.includes('/node_modules/')) {
loc = arr.slice(0, 16).join(" -> ");
loc = arr.slice(0, 16).join(' -> ');
} else {
const pureArr = arr.map((codeLoc) => {
return codeLoc.substring(0, codeLoc.indexOf("(")).trim();
return codeLoc.substring(0, codeLoc.indexOf('(')).trim();
});
loc = pureArr.slice(4, endCutIdx).join(" -> ");
loc = pureArr.slice(4, endCutIdx).join(' -> ');
}
}
}
Expand Down
24 changes: 19 additions & 5 deletions packages/helux-core/src/factory/createDerived.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,39 @@
import { isFn } from '@helux/utils';
import type { Atom, DeriveFn, DeriveFnItem, ICreateDeriveLogicOptions, PlainObject } from '../types/base';
import type { Atom, DeriveFn, ICreateDeriveLogicOptions, IDeriveFnItem, IDeriveTaskOptions, PlainObject } from '../types/base';
import { initDeriveFn } from './common/derived';

export function createDeriveLogic<T extends any = any>(fn: DeriveFn<T> | DeriveFnItem, options?: ICreateDeriveLogicOptions) {
export function createDeriveLogic<T extends any = any>(fn: DeriveFn<T> | IDeriveFnItem, options?: ICreateDeriveLogicOptions) {
const fnItem = isFn(fn) ? { fn } : fn || {};
const fnCtx = initDeriveFn({ ...(options || {}), ...fnItem });
return fnCtx;
}

/**
* 创建派生结果
* 创建派生结果,自动装箱为 { val: T }
*/
export function derive<T = any>(deriveFn: DeriveFn<T> | DeriveFnItem): Atom<T> {
export function derive<T = any>(deriveFn: DeriveFn<T> | IDeriveFnItem): Atom<T> {
const fnCtx = createDeriveLogic<T>(deriveFn, { forAtom: true });
return fnCtx.proxyResult as Atom<T>;
}

/**
* 创建一个返回值为 dict 数据的派生结果,区别于 derive 接口,此接口无自动装箱行为
*/
export function deriveDict<T = PlainObject>(deriveFn: DeriveFn<T> | DeriveFnItem): T {
export function deriveDict<T = PlainObject>(deriveFn: DeriveFn<T> | IDeriveFnItem): T {
const fnCtx = createDeriveLogic<T>(deriveFn);
return fnCtx.proxyResult as T;
}

/**
* 采用柯里化方式生成一个 deriveFnItem ,方便自动推导 deps 返回类型给 IDeriveFnParams
*/
export function defineDeriveTask(deps?: () => any[]) {
return (options: IDeriveTaskOptions): IDeriveFnItem => ({ ...options, deps });
}

/**
* 辅助给直接透传给 defineFullDerive 的某个 deriveFnItem 标记类型
*/
export function defineDeriveFnItem<F extends IDeriveFnItem>(fnItem: F): F {
return fnItem;
}
19 changes: 12 additions & 7 deletions packages/helux-core/src/factory/createShared.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { FROM, STATE_TYPE } from '../consts';
import { runDerive, runDeriveTask } from '../helpers/fnRunner';
import { innerRunDerive, innerRunDeriveTask } from '../helpers/fnRunner';
import { useAtom, useDerived, useGlobalForceUpdate, useLocalForceUpdate, useMutable, useReactive } from '../hooks';
import type { CoreApiCtx } from '../types/api-ctx';
import type { Action, ActionTask, Dict, Fn, IAtomCtx, ICreateOptions, IRunMutateOptions, ISharedCtx } from '../types/base';
Expand Down Expand Up @@ -66,6 +66,7 @@ function defineActions(
actionFn.__fnName = key;
actions[key] = actionFn;
});

return {
actions,
eActions,
Expand All @@ -78,6 +79,7 @@ function defineActions(
function defineMutate(options: { state: any; ldMutate: Dict; mutateFnDict: Dict }) {
const { state, ldMutate, mutateFnDict } = options;
const witnessDict = mutateDict(state)(mutateFnDict);

return {
witnessDict,
getLoading: () => ldMutate.getLoading(witnessDict),
Expand All @@ -94,6 +96,7 @@ function defineMutateDerive(options: { apiCtx: CoreApiCtx; ldMutate: Dict; inita
const [state, , info] = ctx.useState(options);
return [state, info];
};

return { derivedState: state, useDerivedState, ...result };
}

Expand All @@ -105,16 +108,18 @@ function defineFullDerive(options: { apiCtx: CoreApiCtx; deriveFnDict: Dict; thr
const result = derive(deriveFnDict[key]);
derivedResult[key] = result;
helper[key] = {
runDerive: (te?: boolean) => runDerive(result, te ?? throwErr),
runDeriveTask: (te?: boolean) => runDeriveTask(result, te ?? throwErr),
runDerive: (te?: boolean) => innerRunDerive(result, te ?? throwErr),
runDeriveTask: (te?: boolean) => innerRunDeriveTask(result, te ?? throwErr),
useDerived: (options: any) => useDerived(apiCtx, result, options)[0],
useDerivedInfo: (options: any) => useDerived(apiCtx, result, options),
};
});
return {
derivedResult,
helper,
};
/** 对提供给用户使用的结果集做自动拆箱 */
const result = new Proxy(derivedResult, {
get: (t: any, k: any) => derivedResult[k].val,
});

return { result, helper };
}

export function createSharedLogic(innerOptions: IInnerOptions, createOptions?: any): any {
Expand Down
6 changes: 3 additions & 3 deletions packages/helux-core/src/factory/creator/mutateFn.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { enureReturnArr, isPromise, noop, tryAlert } from '@helux/utils';
import { EVENT_NAME, FROM, SCOPE_TYPE } from '../../consts';
import { FROM, SCOPE_TYPE } from '../../consts';
import { getRunningFn, getSafeFnCtx } from '../../factory/common/fnScope';
import { emitPluginEvent } from '../../factory/common/plugin';
import { emitErr } from '../../factory/common/plugin';
import type { TInternal } from '../../factory/creator/buildInternal';
import { FN_DEP_KEYS, REACTIVE_META, TRIGGERED_WATCH } from '../../factory/creator/current';
import { alertDepKeyDeadCycleErr, analyzeErrLog, dcErr, inDeadCycle, probeDepKeyDeadCycle } from '../../factory/creator/deadCycle';
Expand Down Expand Up @@ -249,7 +249,7 @@ export function watchAndCallMutateDict(options: IWatchAndCallMutateDictOptions)
if (!keys.length) return;
const internal = getInternal(target);
const { mutateFnDict, usefulName, forAtom, sharedState } = internal;
const emitErrToPlugin = (err: Error) => emitPluginEvent(internal, EVENT_NAME.ON_ERROR_OCCURED, { err });
const emitErrToPlugin = (err: Error) => emitErr(internal, err);

keys.forEach((descKey) => {
const item = mutateFnDict[descKey];
Expand Down
62 changes: 49 additions & 13 deletions packages/helux-core/src/helpers/fnRunner.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { enureReturnArr, isPromise, noopVoid, tryAlert } from '@helux/utils';
import { ASYNC_TYPE, FROM, WATCH } from '../consts';
import { fakeInternal } from '../factory/common/fake';
import { fakeFnCtx, fakeInternal } from '../factory/common/fake';
import { delComputingFnKey, getFnCtx, getFnCtxByObj, putComputingFnKey } from '../factory/common/fnScope';
import { emitErr } from '../factory/common/plugin';
import type { TInternal } from '../factory/creator/buildInternal';
import { REACTIVE_META, TRIGGERED_WATCH } from '../factory/creator/current';
import { alertDepKeyDeadCycleErr, probeDepKeyDeadCycle, probeFnDeadCycle } from '../factory/creator/deadCycle';
Expand All @@ -12,7 +13,7 @@ import { markComputing } from './fnStatus';

const { MAY_TRANSFER } = ASYNC_TYPE;

interface IRnFnOpt {
interface IRunFnOpt {
sn?: number;
from?: From;
force?: boolean;
Expand All @@ -25,13 +26,18 @@ interface IRnFnOpt {
forceTask?: boolean;
throwErr?: boolean;
depKeys?: string[];
/**
* default: false
* 是否对atom型全量派生结果拆箱
*/
unbox?: boolean;
}

/**
* 执行 watch 函数,内部会尝试检测死循环,防止无限调用情况产生
* TODO 后续优化拦截逻辑,提高可读性
*/
function runWatch(fnCtx: IFnCtx, options: IRnFnOpt) {
function runWatch(fnCtx: IFnCtx, options: IRunFnOpt) {
const { isFirstCall = false, triggerReasons = [], sn = 0, from, internal = fakeInternal, desc } = options;
if (fnCtx.dcErrorInfo.err) {
alertDepKeyDeadCycleErr(internal, fnCtx.dcErrorInfo);
Expand Down Expand Up @@ -102,11 +108,26 @@ function runWatch(fnCtx: IFnCtx, options: IRnFnOpt) {
/**
* 执行 derive 设置函数
*/
export function runFn(fnKey: string, options: IRnFnOpt = {}) {
const { isFirstCall = false, forceFn = false, forceTask = false, throwErr = false, triggerReasons = [], sn = 0, err } = options;
export function runFn(fnKey: string, options: IRunFnOpt = {}) {
const {
isFirstCall = false,
forceFn = false,
forceTask = false,
throwErr = false,
triggerReasons = [],
sn = 0,
err,
unbox = false,
internal = fakeInternal,
} = options;
const fnCtx = getFnCtx(fnKey);
const resultTuple = (err: any = null) => {
if (err && throwErr) throw err;
const ctx = fnCtx || fakeFnCtx;
return unbox ? [ctx.result.val, err] : [ctx.result, err];
};
if (!fnCtx) {
return [null, new Error(`not a valid watch or derive cb for key ${fnKey}`)];
return resultTuple(new Error(`not a valid watch or derive cb for key ${fnKey}`));
}
if (fnCtx.fnType === WATCH) {
return runWatch(fnCtx, options);
Expand Down Expand Up @@ -159,7 +180,7 @@ export function runFn(fnKey: string, options: IRnFnOpt = {}) {
if (shouldRunFn) {
const result = fn(fnParams);
updateAndDrillDown({ data: result });
return [fnCtx.result, null];
return resultTuple();
}

// mark computing for first async task run
Expand All @@ -169,12 +190,12 @@ export function runFn(fnKey: string, options: IRnFnOpt = {}) {
// only works for useDerived
if (isAsyncTransfer) {
updateAndDrillDown({ err });
return [fnCtx.result, null];
return resultTuple();
}
if (fnCtx.asyncType === MAY_TRANSFER) {
const result = fn(fnParams);
updateAndDrillDown({ data: result });
return [fnCtx.result, null];
return resultTuple();
}
if (task) {
let del = noopVoid;
Expand All @@ -199,26 +220,27 @@ export function runFn(fnKey: string, options: IRnFnOpt = {}) {
.then((data: any) => {
del();
updateAndDrillDown({ data });
return [fnCtx.result, null];
return resultTuple();
})
.catch((err: any) => {
// TODO: emit ON_DERIVE_ERROR_OCCURED to plugin
del();
updateAndDrillDown({ err }); // 向下传递错误
if (throwErr) throw err;
return [fnCtx.result, err];
emitErr(internal, err);
return resultTuple(err);
});
}

return [fnCtx.result, null];
return resultTuple(err);
}

/**
* run redive fn by result
*/
export function rerunDeriveFn<T = Dict>(
result: T,
options?: { forceFn?: boolean; forceTask?: boolean; throwErr?: boolean },
options?: { forceFn?: boolean; forceTask?: boolean; throwErr?: boolean; unbox?: boolean },
): [T, Error | null] {
const fnCtx = getFnCtxByObj(result);
if (!fnCtx) {
Expand All @@ -241,6 +263,20 @@ export function runDeriveTask<T = Dict>(result: T, throwErr?: boolean): Promise<
return Promise.resolve(rerunDeriveFn(result, { forceTask: true, throwErr }));
}

/**
* 内部使用的重运行全量派生函数接口,目前提供给 createShared
*/
export function innerRunDerive<T = any>(result: T, throwErr?: boolean): [T, Error | null] {
return rerunDeriveFn(result, { forceFn: true, throwErr, unbox: true });
}

/**
* 内部使用的重运行全量派生函数异步任务,目前提供给 createShared
*/
export function innerRunDeriveTask<T = Dict>(result: T, throwErr?: boolean): Promise<[T, Error | null]> {
return Promise.resolve(rerunDeriveFn(result, { forceTask: true, throwErr, unbox: true }));
}

export function getDeriveLoading<T = Dict>(result: T) {
const fnCtx = getFnCtxByObj(result);
if (fnCtx) {
Expand Down
3 changes: 3 additions & 0 deletions packages/helux-core/src/hooks/useDerived.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import { CoreApiCtx } from '../types/api-ctx';
import type { DerivedDict, IUseDerivedOptions, PlainObject } from '../types/base';
import { useDerivedLogic } from './common/useDerivedLogic';

/**
* 组件使用全量派生结果(注:结果已自动拆箱)
*/
export function useDerived<T = PlainObject>(api: CoreApiCtx, result: DerivedDict<T>, options?: IUseDerivedOptions) {
const fnCtx = useDerivedLogic(api, { result, ...(options || {}) });
const { proxyResult, status, renderInfo } = fnCtx;
Expand Down
Loading

0 comments on commit c59a8ba

Please sign in to comment.