overmind
Version:
Frictionless state management
245 lines • 11 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.createMutationOperator = exports.createOperator = exports.createNextPath = exports.createContext = exports.operatorStopped = exports.operatorStarted = exports.action = void 0;
const internalTypes_1 = require("./internalTypes");
const utils_1 = require("./utils");
function action(operation) {
return createMutationOperator('action', (0, utils_1.getFunctionName)(operation), (err, context, value, next) => {
if (err)
next(err, value);
else {
const result = operation(context, value);
if ((0, utils_1.isPromise)(result)) {
next(null, result.then((resolvedValue) => resolvedValue));
}
else {
next(null, result);
}
}
});
}
exports.action = action;
function operatorStarted(type, arg, context) {
if (process.env.NODE_ENV === 'production') {
return;
}
const name = typeof arg === 'function' ? arg.displayName || arg.name : String(arg);
context.execution.isRunning = true;
context.execution.emit(internalTypes_1.EventType.OPERATOR_START, Object.assign(Object.assign({}, context.execution), { name,
type }));
}
exports.operatorStarted = operatorStarted;
function operatorStopped(context, value, details = {}) {
if (process.env.NODE_ENV === 'production') {
if (value instanceof Promise) {
context.execution.emit(internalTypes_1.EventType.OPERATOR_ASYNC, Object.assign(Object.assign({}, context.execution), { isAsync: true }));
}
return;
}
const evaluatedDetails = {
error: details.error ? details.error.message : undefined,
isIntercepted: Boolean(details.isIntercepted),
isSkipped: Boolean(details.isSkipped),
};
if (value instanceof Promise) {
value
.then((promiseValue) => {
context.execution.isRunning = false;
context.execution.emit(internalTypes_1.EventType.OPERATOR_END, Object.assign(Object.assign(Object.assign({}, context.execution), { result: promiseValue, isAsync: true }), evaluatedDetails));
})
.catch(() => {
// Make sure an error does not cause uncaught
});
}
else {
context.execution.isRunning = false;
context.execution.emit(internalTypes_1.EventType.OPERATOR_END, Object.assign(Object.assign(Object.assign({}, context.execution), { result: value, isAsync: false }), evaluatedDetails));
}
}
exports.operatorStopped = operatorStopped;
function createContext(context, value, path) {
if (process.env.NODE_ENV === 'production') {
return Object.assign(Object.assign({}, context), { value });
}
const newExecution = Object.assign(Object.assign({}, context.execution), { operatorId: context.execution.getNextOperatorId(), path: path || context.execution.path });
const mutationTrees = [];
return Object.assign(Object.assign({}, context), { actions: (0, utils_1.createActionsProxy)(context.actions[utils_1.ORIGINAL_ACTIONS] || context.actions, (action) => {
return (value) => action(value, newExecution.isRunning ? newExecution : null);
}), value, execution: newExecution, effects: context.execution.trackEffects(newExecution), flush: context.parentExecution
? context.parentExecution.flush
: (isAsync) => {
return this.proxyStateTree.flush(mutationTrees, isAsync);
}, getMutationTree: context.parentExecution
? context.parentExecution.getMutationTree
: () => {
const mutationTree = this.proxyStateTree.getMutationTree();
mutationTrees.push(mutationTree);
if (this.mode.mode === utils_1.MODE_TEST) {
mutationTree.onMutation((mutation) => {
this.addExecutionMutation(mutation);
});
}
return mutationTree;
} });
}
exports.createContext = createContext;
function createNextPath(next) {
if (process.env.NODE_ENV === 'production') {
return next;
}
return (err, context) => {
const newContext = Object.assign(Object.assign({}, context), { execution: Object.assign(Object.assign({}, context.execution), { path: context.execution.path.slice(0, context.execution.path.length - 1) }) });
if (err)
next(err, newContext);
else
next(null, newContext);
};
}
exports.createNextPath = createNextPath;
function createOperator(type, name, cb) {
const operator = (err, context, next, final) => {
operatorStarted(type, name, context);
let nextIsCalled = false;
try {
cb(err, {
state: context.state,
effects: context.effects,
actions: context.actions,
execution: context.execution,
addFlushListener: context.addFlushListener,
addMutationListener: context.addMutationListener,
reaction: context.reaction,
}, context.value, (err, value, options = {}) => {
function run(err, value) {
if (options.path) {
const newContext = createContext(context, value, context.execution.path &&
context.execution.path.concat(options.path.name));
const nextWithPath = createNextPath(next);
const operatorToRun = options.path.operator[utils_1.IS_OPERATOR]
? options.path.operator
: action(options.path.operator);
operatorToRun(err, newContext, (...args) => {
operatorStopped(context, args[1].value);
nextWithPath(...args);
});
}
else {
operatorStopped(context, err || value, {
isSkipped: err ? true : options.isSkipped,
});
next(err, createContext(context, value));
}
}
if (value && value instanceof Promise) {
value
.then((promiseValue) => run(err, promiseValue))
.catch((promiseError) => run(promiseError, promiseError));
}
else {
nextIsCalled = true;
run(err, value);
}
}, (err, value) => {
nextIsCalled = true;
operatorStopped(context, err || value, {
isSkipped: Boolean(err),
isIntercepted: !err,
});
final(err, createContext(context, value));
});
}
catch (error) {
nextIsCalled = true;
operatorStopped(context, context.value, {
error,
});
next(error, createContext(context, context.value));
}
if (!nextIsCalled) {
context.execution.emit(internalTypes_1.EventType.OPERATOR_ASYNC, Object.assign(Object.assign({}, context.execution), { isAsync: true }));
}
};
operator[utils_1.IS_OPERATOR] = true;
return operator;
}
exports.createOperator = createOperator;
function createMutationOperator(type, name, cb) {
const operator = (err, context, next, final) => {
operatorStarted(type, name, context);
const mutationTree = context.execution.getMutationTree();
if (!(process.env.NODE_ENV === 'production')) {
mutationTree.onMutation((mutation) => {
context.execution.emit(internalTypes_1.EventType.MUTATIONS, Object.assign(Object.assign({}, context.execution), { mutations: [mutation] }));
});
}
let nextIsCalled = false;
try {
cb(err, {
state: mutationTree.state,
effects: context.effects,
actions: context.actions,
execution: context.execution,
addFlushListener: context.addFlushListener,
addMutationListener: context.addMutationListener,
reaction: context.reaction,
}, process.env.NODE_ENV === 'production'
? context.value
: context.execution.scopeValue(context.value, mutationTree), (err, value, options = {}) => {
function run(err, value) {
operatorStopped(context, err || value, {
isSkipped: err ? true : options.isSkipped,
});
mutationTree.dispose();
next(err, createContext(context, value));
}
if (value && value instanceof Promise) {
value
.then((promiseValue) => run(err, promiseValue))
.catch((promiseError) => run(promiseError, promiseError));
}
else {
nextIsCalled = true;
run(err, value);
}
}, (err, value) => {
nextIsCalled = true;
operatorStopped(context, err || value, {
isSkipped: Boolean(err),
isIntercepted: !err,
});
final(err, createContext(context, value));
});
if (!(process.env.NODE_ENV === 'production')) {
let pendingFlush;
mutationTree.onMutation(() => {
if (pendingFlush) {
clearTimeout(pendingFlush);
}
pendingFlush = setTimeout(() => {
const flushData = context.execution.flush(true);
if (flushData.mutations.length) {
context.execution.send({
type: 'flush',
data: Object.assign(Object.assign(Object.assign({}, context.execution), flushData), { mutations: flushData.mutations }),
});
}
});
});
}
}
catch (error) {
nextIsCalled = true;
operatorStopped(context, context.value, {
error,
});
next(error, createContext(context, context.value));
}
if (!nextIsCalled) {
context.execution.emit(internalTypes_1.EventType.OPERATOR_ASYNC, Object.assign(Object.assign({}, context.execution), { isAsync: true }));
}
};
operator[utils_1.IS_OPERATOR] = true;
return operator;
}
exports.createMutationOperator = createMutationOperator;
//# sourceMappingURL=operator.js.map
;