@nocobase/flow-engine
Version:
A standalone flow engine for NocoBase, managing workflows, models, and actions.
1,256 lines (1,255 loc) • 51.4 kB
JavaScript
/**
* This file is part of the NocoBase (R) project.
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
* Authors: NocoBase Team.
*
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
* For more information, please refer to: https://www.nocobase.com/agreement.
*/
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __typeError = (msg) => {
throw TypeError(msg);
};
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
var flowContext_exports = {};
__export(flowContext_exports, {
FlowContext: () => FlowContext,
FlowEngineContext: () => FlowEngineContext,
FlowForkModelContext: () => FlowForkModelContext,
FlowModelContext: () => FlowModelContext,
FlowRunjsContext: () => FlowRunjsContext,
FlowRuntimeContext: () => FlowRuntimeContext
});
module.exports = __toCommonJS(flowContext_exports);
var import_reactive = require("@formily/reactive");
var antd = __toESM(require("antd"));
var import_lodash = __toESM(require("lodash"));
var import_qs = __toESM(require("qs"));
var import_react = __toESM(require("react"));
var import_Acl = require("./acl/Acl");
var import_ContextPathProxy = require("./ContextPathProxy");
var import_data_source = require("./data-source");
var import_flowEngine = require("./flowEngine");
var import_flowI18n = require("./flowI18n");
var import_JSRunner = require("./JSRunner");
var import_models = require("./models");
var import_resources = require("./resources");
var import_utils = require("./utils");
var import_exceptions = require("./utils/exceptions");
var import_params_resolvers = require("./utils/params-resolvers");
var import_serverContextParams = require("./utils/serverContextParams");
var _proxy, _FlowContext_instances, createChildNodes_fn, findMetaByPath_fn, findMetaInDelegatesDeep_fn, findMetaInProperty_fn, resolvePathInMeta_fn, resolvePathInMetaAsync_fn, buildParentTitles_fn, toTreeNode_fn;
function isRecordRefLike(val) {
return !!(val && typeof val === "object" && "collection" in val && "filterByTk" in val);
}
__name(isRecordRefLike, "isRecordRefLike");
function filterBuilderOutputByPaths(built, neededPaths) {
if (!neededPaths || neededPaths.length === 0) return void 0;
if (isRecordRefLike(built)) return built;
if (built && typeof built === "object" && !Array.isArray(built)) {
const out = {};
for (const [k, v] of Object.entries(built)) {
const hit = neededPaths.some((p) => p === k || p.startsWith(`${k}.`) || p.startsWith(`${k}[`));
if (hit) out[k] = v;
}
return out;
}
return void 0;
}
__name(filterBuilderOutputByPaths, "filterBuilderOutputByPaths");
const _FlowContext = class _FlowContext {
constructor() {
__privateAdd(this, _FlowContext_instances);
__publicField(this, "_props", {});
__publicField(this, "_methods", {});
__publicField(this, "_cache", {});
__publicField(this, "_observableCache", import_reactive.observable.shallow({}));
__publicField(this, "_delegates", []);
__publicField(this, "_pending", {});
__privateAdd(this, _proxy, null);
__publicField(this, "_metaNodeCache", /* @__PURE__ */ new WeakMap());
return this.createProxy();
}
createProxy() {
if (__privateGet(this, _proxy)) {
return __privateGet(this, _proxy);
}
__privateSet(this, _proxy, new Proxy(this, {
get: /* @__PURE__ */ __name((target, key, receiver) => {
if (typeof key === "string") {
if (Reflect.has(target, key)) {
const val = Reflect.get(target, key, receiver);
if (typeof val === "function") return val.bind(target);
return val;
}
if (Object.prototype.hasOwnProperty.call(target._props, key)) {
return target._getOwnProperty(key, this.createProxy());
}
if (Object.prototype.hasOwnProperty.call(target._methods, key)) {
return target._getOwnMethod(key, this.createProxy());
}
const found = this._findInDelegates(target._delegates, key);
if (found !== void 0) return found.result;
return void 0;
}
return Reflect.get(target, key, receiver);
}, "get"),
has: /* @__PURE__ */ __name((target, key) => {
if (typeof key === "string") {
if (Reflect.has(target, key)) return true;
if (Object.prototype.hasOwnProperty.call(target._props, key)) return true;
if (Object.prototype.hasOwnProperty.call(target._methods, key)) return true;
if (this._hasInDelegates(target._delegates, key)) return true;
}
return Reflect.has(target, key);
}, "has")
}));
return __privateGet(this, _proxy);
}
defineProperty(key, options) {
var _a;
if (this._props[key] && ((_a = this._props[key]) == null ? void 0 : _a.once)) {
return;
}
const oldOptions = this._props[key];
if (oldOptions == null ? void 0 : oldOptions.meta) {
this._clearMetaNodeCacheFor(oldOptions.meta);
}
this._props[key] = options;
delete this._observableCache[key];
delete this._cache[key];
Object.defineProperty(this, key, {
configurable: true,
enumerable: true,
get: /* @__PURE__ */ __name(() => this._getOwnProperty(key, this.createProxy()), "get")
});
}
defineMethod(name, fn, des) {
this._methods[name] = fn;
Object.defineProperty(this, name, {
configurable: true,
enumerable: false,
writable: false,
value: fn.bind(this.createProxy())
});
}
removeCache(key) {
if (key in this._observableCache) {
delete this._observableCache[key];
return true;
}
if (key in this._cache) {
delete this._cache[key];
return true;
}
if (key in this._pending) {
delete this._pending[key];
return true;
}
for (const delegate of this._delegates) {
if (delegate.removeCache(key)) {
return true;
}
}
}
delegate(ctx) {
if (!(ctx instanceof _FlowContext)) {
throw new Error("Delegate must be an instance of FlowContext");
}
if (this._delegates.includes(ctx)) {
console.warn(`[FlowContext] delegate - skip duplicate delegate: ${this._delegates.length}`);
return;
}
this._delegates.unshift(ctx);
}
addDelegate(ctx) {
if (!(ctx instanceof _FlowContext)) {
throw new Error("Delegate must be an instance of FlowContext");
}
if (!this._delegates.includes(ctx)) {
this._delegates.unshift(ctx);
}
}
clearDelegates() {
this._delegates = [];
this._metaNodeCache = /* @__PURE__ */ new WeakMap();
}
removeDelegate(ctx) {
if (!(ctx instanceof _FlowContext)) {
throw new Error("Delegate must be an instance of FlowContext");
}
const index = this._delegates.indexOf(ctx);
if (index !== -1) {
this._delegates.splice(index, 1);
}
}
/**
* 清除特定 meta 对象的缓存
*/
_clearMetaNodeCacheFor(meta) {
this._metaNodeCache.delete(meta);
}
has(key) {
return !!this._props[key];
}
/**
* 获取属性元数据树
* 返回的 MetaTreeNode 中可能包含异步的延迟加载逻辑
* @param value 可选参数,指定要获取的属性路径,格式: "{{ ctx.propertyName }}"
* @returns MetaTreeNode[] 根级属性的元数据树,或指定路径的子树
*
* @example
* // 同步调用,获取完整 meta tree
* const metaTree = flowContext.getPropertyMetaTree();
*
* // 获取指定属性的子树
* const subTree = flowContext.getPropertyMetaTree("{{ ctx.user }}");
*
* // 获取多层级属性的子树
* const profileTree = flowContext.getPropertyMetaTree("{{ ctx.user.profile }}");
*/
getPropertyMetaTree(value, options) {
const metaMap = this._getPropertiesMeta();
if (value) {
const propertyPath = (0, import_utils.extractPropertyPath)(value);
if (propertyPath && propertyPath.length > 0) {
const loadChildrenFrom = /* @__PURE__ */ __name(async (metaOrFactory, fullPath, finalKey) => {
try {
const meta = typeof metaOrFactory === "function" ? await metaOrFactory() : metaOrFactory;
if (!(meta == null ? void 0 : meta.properties)) return [];
let props = meta.properties;
if (typeof props === "function") {
const resolved = await props();
meta.properties = resolved;
props = resolved;
}
const childNodes = __privateMethod(this, _FlowContext_instances, createChildNodes_fn).call(this, props, fullPath, [], meta);
return Array.isArray(childNodes) ? childNodes : await childNodes();
} catch (error) {
console.warn(`Failed to load meta for ${finalKey}:`, error);
return [];
}
}, "loadChildrenFrom");
const targetMeta = __privateMethod(this, _FlowContext_instances, findMetaByPath_fn).call(this, propertyPath);
if (targetMeta) {
const [finalKey, metaOrFactory, fullPath] = targetMeta;
const depth = propertyPath.length;
if (depth === 1) {
if (typeof metaOrFactory === "function") {
return () => loadChildrenFrom(metaOrFactory, fullPath, finalKey);
}
if (metaOrFactory.properties) {
if (typeof metaOrFactory.properties === "function") {
return () => loadChildrenFrom(metaOrFactory, fullPath, finalKey);
}
const childNodes = __privateMethod(this, _FlowContext_instances, createChildNodes_fn).call(this, metaOrFactory.properties, fullPath, [], metaOrFactory);
return Array.isArray(childNodes) ? childNodes : [];
}
return [];
}
if (typeof metaOrFactory === "function") {
if (options == null ? void 0 : options.flatten) {
return () => loadChildrenFrom(metaOrFactory, fullPath, finalKey);
}
const parentTitles = __privateMethod(this, _FlowContext_instances, buildParentTitles_fn).call(this, fullPath);
return [__privateMethod(this, _FlowContext_instances, toTreeNode_fn).call(this, finalKey, metaOrFactory, fullPath, parentTitles)];
}
if (metaOrFactory.properties) {
const parentTitles = [...__privateMethod(this, _FlowContext_instances, buildParentTitles_fn).call(this, fullPath), metaOrFactory.title];
const childNodes = __privateMethod(this, _FlowContext_instances, createChildNodes_fn).call(this, metaOrFactory.properties, fullPath, parentTitles, metaOrFactory);
return Array.isArray(childNodes) ? childNodes : [];
}
return [];
}
return [];
} else if (propertyPath === null) {
console.warn(
`[FlowContext] getPropertyMetaTree - unsupported value format: "${value}". Only "{{ ctx.propertyName }}" format is supported. Returning empty meta tree.`
);
return [];
}
}
const sorted = Object.entries(metaMap).sort(([, a], [, b]) => {
const sa = (typeof a === "function" ? a.sort : a == null ? void 0 : a.sort) ?? 0;
const sb = (typeof b === "function" ? b.sort : b == null ? void 0 : b.sort) ?? 0;
return sb - sa;
});
return sorted.map(([key, metaOrFactory]) => __privateMethod(this, _FlowContext_instances, toTreeNode_fn).call(this, key, metaOrFactory, [key], []));
}
_getPropertiesMeta() {
const metaMap = {};
for (const delegate of this._delegates) {
Object.assign(metaMap, delegate._getPropertiesMeta());
}
for (const [key, options] of Object.entries(this._props)) {
if (options.meta) {
metaMap[key] = typeof options.meta === "function" ? options.meta : options.meta;
}
}
return metaMap;
}
// 只查找自身 _props
_getOwnProperty(key, currentContext) {
const options = this._props[key];
if (!options) return void 0;
if ("value" in options) {
return options.value;
}
if (options.get) {
if (options.cache === false) {
return options.get(currentContext);
}
const cacheKey = options.observable ? "_observableCache" : "_cache";
if (key in this[cacheKey]) {
return this[cacheKey][key];
}
if (this._pending[key]) return this._pending[key];
const result = options.get(this.createProxy());
const isPromise = typeof result === "object" && result !== null && typeof result.then === "function" || typeof result === "function" && typeof result.then === "function";
if (isPromise) {
this._pending[key] = result.then(
(v) => {
this[cacheKey][key] = v;
delete this._pending[key];
return v;
},
(err) => {
delete this._pending[key];
throw err;
}
);
return this._pending[key];
}
this[cacheKey][key] = result;
return result;
}
return void 0;
}
// 只查找自身 _methods
_getOwnMethod(key, flowContext) {
const fn = this._methods[key];
if (typeof fn === "function") {
return fn.bind(flowContext);
}
return fn;
}
_findPropertyInDelegates(delegates, key) {
for (const delegate of delegates) {
if (Object.prototype.hasOwnProperty.call(delegate._props, key)) {
return delegate._props[key];
}
const found = this._findPropertyInDelegates(delegate._delegates, key);
if (found !== void 0) return found;
}
return void 0;
}
_findInDelegates(delegates, key) {
for (const delegate of delegates) {
if (Object.prototype.hasOwnProperty.call(delegate._props, key)) {
return {
result: delegate._getOwnProperty(key, this.createProxy())
};
}
if (Object.prototype.hasOwnProperty.call(delegate._methods, key)) {
return {
result: delegate._getOwnMethod(key, this.createProxy())
};
}
const found = this._findInDelegates(delegate._delegates, key);
if (found !== void 0) return found;
}
return void 0;
}
// 递归查找委托链
_hasInDelegates(delegates, key) {
for (const delegate of delegates) {
if (Object.prototype.hasOwnProperty.call(delegate._props, key)) return true;
if (Object.prototype.hasOwnProperty.call(delegate._methods, key)) return true;
if (this._hasInDelegates(delegate._delegates, key)) return true;
}
return false;
}
/**
* 获取属性定义选项(包含代理链)。
*
* - 优先查找当前上下文自身通过 defineProperty 注册的属性定义
* - 若自身不存在,则沿委托链(delegates)向上查找第一个命中的定义
*
* @param key 顶层属性名(例如 'user'、'view')
* @returns 属性定义选项,或 undefined(未定义)
*/
getPropertyOptions(key) {
if (Object.prototype.hasOwnProperty.call(this._props, key)) {
return this._props[key];
}
return this._findPropertyInDelegates(this._delegates, key);
}
};
_proxy = new WeakMap();
_FlowContext_instances = new WeakSet();
createChildNodes_fn = /* @__PURE__ */ __name(function(properties, parentPaths = [], parentTitles = [], parentMeta) {
return typeof properties === "function" ? async () => {
const resolved = await properties();
if (parentMeta) {
parentMeta.properties = resolved;
}
const entries = Object.entries(resolved);
entries.sort(([, a], [, b]) => ((b == null ? void 0 : b.sort) ?? 0) - ((a == null ? void 0 : a.sort) ?? 0));
return entries.map(([name, meta]) => __privateMethod(this, _FlowContext_instances, toTreeNode_fn).call(this, name, meta, [...parentPaths, name], parentTitles));
} : Object.entries(properties).sort(([, a], [, b]) => ((b == null ? void 0 : b.sort) ?? 0) - ((a == null ? void 0 : a.sort) ?? 0)).map(([name, meta]) => __privateMethod(this, _FlowContext_instances, toTreeNode_fn).call(this, name, meta, [...parentPaths, name], parentTitles));
}, "#createChildNodes");
/**
* 根据属性路径查找对应的 meta
* @param propertyPath 属性路径数组,例如 ["aaa", "bbb"]
* @returns [finalKey, metaOrFactory, fullPath] 或 null
*/
findMetaByPath_fn = /* @__PURE__ */ __name(function(propertyPath) {
if (propertyPath.length === 0) return null;
const [firstKey, ...remainingPath] = propertyPath;
const ownProperty = this._props[firstKey];
if (ownProperty == null ? void 0 : ownProperty.meta) {
return __privateMethod(this, _FlowContext_instances, findMetaInProperty_fn).call(this, firstKey, ownProperty.meta, remainingPath, [firstKey]);
}
const deepMeta = __privateMethod(this, _FlowContext_instances, findMetaInDelegatesDeep_fn).call(this, this._delegates, firstKey);
if (deepMeta) {
return __privateMethod(this, _FlowContext_instances, findMetaInProperty_fn).call(this, firstKey, deepMeta, remainingPath, [firstKey]);
}
return null;
}, "#findMetaByPath");
/**
* 递归在委托链中查找指定 key 的 meta(只返回 metaOrFactory,不解析路径)。
*/
findMetaInDelegatesDeep_fn = /* @__PURE__ */ __name(function(delegates, key) {
for (const delegate of delegates) {
const prop = delegate._props[key];
if (prop == null ? void 0 : prop.meta) return prop.meta;
const deeper = __privateMethod(this, _FlowContext_instances, findMetaInDelegatesDeep_fn).call(this, delegate._delegates, key);
if (deeper) return deeper;
}
return null;
}, "#findMetaInDelegatesDeep");
/**
* 在给定属性的 meta 中查找剩余路径
*/
findMetaInProperty_fn = /* @__PURE__ */ __name(function(currentKey, metaOrFactory, remainingPath, currentPath) {
if (remainingPath.length === 0) {
return [currentKey, metaOrFactory, currentPath];
}
if (typeof metaOrFactory === "function") {
const finalKey = remainingPath[remainingPath.length - 1];
const finalPath = [...currentPath, ...remainingPath];
const wrappedFactory = /* @__PURE__ */ __name(async () => {
const resolvedMeta = await metaOrFactory();
const result = await __privateMethod(this, _FlowContext_instances, resolvePathInMetaAsync_fn).call(this, resolvedMeta, remainingPath);
return result;
}, "wrappedFactory");
return [finalKey, wrappedFactory, finalPath];
}
if (metaOrFactory.properties) {
const [nextKey, ...restPath] = remainingPath;
const nextPath = [...currentPath, nextKey];
if (typeof metaOrFactory.properties === "function") {
const finalKey = remainingPath[remainingPath.length - 1];
const finalPath = [...currentPath, ...remainingPath];
const wrappedFactory = /* @__PURE__ */ __name(async () => {
const propertiesFactory = metaOrFactory.properties;
const resolvedProperties = await propertiesFactory();
metaOrFactory.properties = resolvedProperties;
const startMeta = resolvedProperties[nextKey];
if (!startMeta) {
throw new Error(`Property ${nextKey} not found in resolved properties`);
}
const result = await __privateMethod(this, _FlowContext_instances, resolvePathInMetaAsync_fn).call(this, startMeta, restPath);
return result;
}, "wrappedFactory");
return [finalKey, wrappedFactory, finalPath];
}
const nextMeta = metaOrFactory.properties[nextKey];
if (nextMeta) {
return __privateMethod(this, _FlowContext_instances, findMetaInProperty_fn).call(this, nextKey, nextMeta, restPath, nextPath);
}
}
return null;
}, "#findMetaInProperty");
/**
* 在给定的 meta 中递归解析路径
*/
resolvePathInMeta_fn = /* @__PURE__ */ __name(function(meta, path) {
if (path.length === 0) {
return meta;
}
let current = meta;
for (const key of path) {
const properties = import_lodash.default.get(current, "properties");
if (!properties || typeof properties === "function") {
return null;
}
current = import_lodash.default.get(properties, key);
if (!current) {
return null;
}
}
return current;
}, "#resolvePathInMeta");
resolvePathInMetaAsync_fn = /* @__PURE__ */ __name(async function(meta, path) {
if (path.length === 0) return meta;
let current = meta;
for (const key of path) {
let properties = import_lodash.default.get(current, "properties");
if (!properties) {
throw new Error(`Property path not found: ${path.join(".")}`);
}
if (typeof properties === "function") {
const resolved = await properties();
current.properties = resolved;
properties = resolved;
}
const next = properties[key];
if (!next) {
throw new Error(`Property ${key} not found while resolving path: ${path.join(".")}`);
}
current = next;
}
return current;
}, "#resolvePathInMetaAsync");
/**
* 构建 parentTitles 数组,通过递归查找每个路径层级对应的 meta title
* @param propertyPath 属性路径数组,例如 ['aaa', 'bbb', 'ccc']
* @param excludeLastLevel 是否排除最后一层,默认为 true(parentTitles 不包含当前节点)
* @returns string[] 父级标题数组
*/
buildParentTitles_fn = /* @__PURE__ */ __name(function(propertyPath, excludeLastLevel = true) {
if (propertyPath.length === 0) return [];
const pathToProcess = excludeLastLevel ? propertyPath.slice(0, -1) : propertyPath;
if (pathToProcess.length === 0) return [];
const parentTitles = [];
let currentMetas = this._getPropertiesMeta();
for (let i = 0; i < pathToProcess.length; i++) {
const currentKey = pathToProcess[i];
const currentMeta = currentMetas[currentKey];
if (!currentMeta || typeof currentMeta === "function") {
parentTitles.push(currentKey);
break;
}
parentTitles.push(currentMeta.title || currentKey);
if (i < pathToProcess.length - 1 && currentMeta.properties && typeof currentMeta.properties !== "function") {
currentMetas = currentMeta.properties;
} else if (i < pathToProcess.length - 1) {
for (let j = i + 1; j < pathToProcess.length; j++) {
parentTitles.push(pathToProcess[j]);
}
break;
}
}
return parentTitles;
}, "#buildParentTitles");
toTreeNode_fn = /* @__PURE__ */ __name(function(name, metaOrFactory, paths = [name], parentTitles = []) {
const cached = this._metaNodeCache.get(metaOrFactory);
if (cached) {
cached.paths = paths;
cached.parentTitles = parentTitles.length > 0 ? parentTitles : void 0;
return cached;
}
let node;
const computeDisabledFromMeta = /* @__PURE__ */ __name((m) => {
if (!m) return { disabled: false };
const disabledVal = typeof m.disabled === "function" ? m.disabled() : m.disabled;
const reason = typeof m.disabledReason === "function" ? m.disabledReason() : m.disabledReason;
return { disabled: !!disabledVal, reason };
}, "computeDisabledFromMeta");
if (typeof metaOrFactory === "function") {
const initialTitle = name;
const hasChildrenHint = metaOrFactory.hasChildren;
node = {
name,
title: metaOrFactory.title || initialTitle,
// 初始使用 name 作为 title
type: "object",
// 初始类型
interface: void 0,
uiSchema: void 0,
paths,
parentTitles: parentTitles.length > 0 ? parentTitles : void 0,
disabled: /* @__PURE__ */ __name(() => {
const maybe = metaOrFactory();
if (maybe && typeof maybe["then"] === "function") return false;
return computeDisabledFromMeta(maybe).disabled;
}, "disabled"),
disabledReason: /* @__PURE__ */ __name(() => {
const maybe = metaOrFactory();
if (maybe && typeof maybe["then"] === "function") return void 0;
return computeDisabledFromMeta(maybe).reason;
}, "disabledReason"),
// 注意:即便 hasChildren === false,也只是“没有子节点”的 UI 提示;
// 节点自身依然通过 meta 工厂保持惰性特性(需要时可解析出 title/type 等)。
// 这里仅在 hasChildren !== false 时,提供子节点的懒加载逻辑。
children: hasChildrenHint === false ? void 0 : async () => {
try {
const meta = await metaOrFactory();
const finalTitle = (meta == null ? void 0 : meta.title) || name;
node.title = finalTitle;
node.type = meta == null ? void 0 : meta.type;
node.interface = meta == null ? void 0 : meta.interface;
node.uiSchema = meta == null ? void 0 : meta.uiSchema;
if (!(meta == null ? void 0 : meta.properties)) return [];
const childNodes = __privateMethod(this, _FlowContext_instances, createChildNodes_fn).call(this, meta.properties, paths, [...parentTitles, finalTitle], meta);
const resolvedChildren = Array.isArray(childNodes) ? childNodes : await childNodes();
node.children = resolvedChildren;
return resolvedChildren;
} catch (error) {
console.warn(`Failed to load meta for ${name}:`, error);
return [];
}
}
};
} else {
const nodeTitle = metaOrFactory.title;
const { disabled, reason } = computeDisabledFromMeta(metaOrFactory);
node = {
name,
title: nodeTitle,
type: metaOrFactory.type,
interface: metaOrFactory.interface,
uiSchema: metaOrFactory.uiSchema,
paths,
parentTitles: parentTitles.length > 0 ? parentTitles : void 0,
disabled,
disabledReason: reason,
children: metaOrFactory.properties ? __privateMethod(this, _FlowContext_instances, createChildNodes_fn).call(this, metaOrFactory.properties, paths, [...parentTitles, nodeTitle], metaOrFactory) : void 0
};
}
this._metaNodeCache.set(metaOrFactory, node);
return node;
}, "#toTreeNode");
__name(_FlowContext, "FlowContext");
let FlowContext = _FlowContext;
const _FlowRunjsContext = class _FlowRunjsContext extends FlowContext {
constructor(delegate) {
super();
this.addDelegate(delegate);
this.defineProperty("React", { value: import_react.default });
this.defineProperty("antd", { value: antd });
this.defineMethod(
"dispatchModelEvent",
async (modelOrUid, eventName, inputArgs) => {
var _a, _b;
let model = null;
if (typeof modelOrUid === "string") {
model = await this.engine.loadModel({ uid: modelOrUid });
} else if (modelOrUid instanceof import_models.FlowModel) {
model = modelOrUid;
}
if (model) {
model.context.addDelegate(this);
model.dispatchEvent(eventName, { navigation: false, ...(_b = (_a = this.model) == null ? void 0 : _a["getInputArgs"]) == null ? void 0 : _b.call(_a), ...inputArgs });
} else {
this.message.error(this.t("Model with ID {{uid}} not found", { uid: modelOrUid }));
}
}
);
}
};
__name(_FlowRunjsContext, "FlowRunjsContext");
let FlowRunjsContext = _FlowRunjsContext;
const _BaseFlowEngineContext = class _BaseFlowEngineContext extends FlowContext {
};
__name(_BaseFlowEngineContext, "BaseFlowEngineContext");
let BaseFlowEngineContext = _BaseFlowEngineContext;
const _BaseFlowModelContext = class _BaseFlowModelContext extends BaseFlowEngineContext {
};
__name(_BaseFlowModelContext, "BaseFlowModelContext");
let BaseFlowModelContext = _BaseFlowModelContext;
const _FlowEngineContext = class _FlowEngineContext extends BaseFlowEngineContext {
// public dataSourceManager: DataSourceManager;
constructor(engine) {
if (!(engine instanceof import_flowEngine.FlowEngine)) {
throw new Error("Invalid FlowEngine instance");
}
super();
this.engine = engine;
this.engine = engine;
const dataSourceManager = new import_data_source.DataSourceManager();
dataSourceManager.setFlowEngine(this.engine);
const mainDataSource = new import_data_source.DataSource({
key: "main",
displayName: "Main"
});
dataSourceManager.addDataSource(mainDataSource);
this.defineProperty("engine", {
value: this.engine
});
this.defineProperty("sql", {
get: /* @__PURE__ */ __name(() => new import_resources.FlowSQLRepository(this), "get")
});
this.defineProperty("dataSourceManager", {
value: dataSourceManager
});
const i18n = new import_flowI18n.FlowI18n(this);
this.defineMethod("t", (keyOrTemplate, options) => {
return i18n.translate(keyOrTemplate, options);
});
this.defineMethod("runjs", async (code, variables, options) => {
const mergedGlobals = { ...(options == null ? void 0 : options.globals) || {}, ...variables || {} };
const runner = this.createJSRunner({
...options || {},
globals: mergedGlobals
});
return runner.run(code);
});
this.defineMethod("renderJson", function(template) {
return this.resolveJsonTemplate(template);
});
this.defineMethod("resolveJsonTemplate", async function(template) {
var _a, _b;
const used = (0, import_utils.extractUsedVariablePaths)(template);
const usedVarNames = Object.keys(used || {});
if (!usedVarNames.length) {
return (0, import_utils.resolveExpressions)(template, this);
}
const serverVarPaths = {};
for (const varName of usedVarNames) {
const paths = used[varName] || [];
const opt = this.getPropertyOptions(varName);
const mark = opt == null ? void 0 : opt.resolveOnServer;
if (mark === true) {
serverVarPaths[varName] = paths;
} else if (typeof mark === "function") {
const filtered = paths.filter((p) => {
try {
return !!mark(p);
} catch (_2) {
return false;
}
});
if (filtered.length) serverVarPaths[varName] = filtered;
}
}
const needServer = Object.keys(serverVarPaths).length > 0;
let serverResolved = template;
if (needServer) {
const collectFromMeta = /* @__PURE__ */ __name(async () => {
var _a2;
const out = {};
try {
const metas = (_a2 = this._getPropertiesMeta) == null ? void 0 : _a2.call(this);
if (!metas || typeof metas !== "object") return out;
for (const [key, metaOrFactory] of Object.entries(metas)) {
if (!serverVarPaths[key]) continue;
try {
let meta;
if (typeof metaOrFactory === "function") {
const fn = metaOrFactory;
meta = await fn();
} else {
meta = metaOrFactory;
}
if (!meta || typeof meta !== "object") continue;
const builder = meta.buildVariablesParams;
if (typeof builder !== "function") continue;
const built = await builder(this);
if (!built) continue;
const neededPaths = serverVarPaths[key] || [];
const filtered = filterBuilderOutputByPaths(built, neededPaths);
if (filtered && (typeof filtered !== "object" || Object.keys(filtered).length)) {
out[key] = filtered;
}
} catch (_2) {
}
}
} catch (_2) {
}
return out;
}, "collectFromMeta");
const inputFromMeta = await collectFromMeta();
const autoInput = { ...inputFromMeta };
const autoContextParams = Object.keys(autoInput).length ? (0, import_serverContextParams.buildServerContextParams)(this, autoInput) : void 0;
if (this.api) {
try {
serverResolved = await (0, import_params_resolvers.enqueueVariablesResolve)(this, {
template,
contextParams: autoContextParams || {}
});
} catch (e) {
(_b = (_a = this.logger) == null ? void 0 : _a.warn) == null ? void 0 : _b.call(_a, { err: e }, "variables:resolve failed, fallback to client-only");
serverResolved = template;
}
}
}
return (0, import_utils.resolveExpressions)(serverResolved, this);
});
this.defineProperty("requirejs", {
get: /* @__PURE__ */ __name(() => {
var _a, _b;
return (_b = (_a = this.app) == null ? void 0 : _a.requirejs) == null ? void 0 : _b.requirejs;
}, "get")
});
this.defineProperty("token", {
get: /* @__PURE__ */ __name(() => {
var _a, _b;
return (_b = (_a = this.api) == null ? void 0 : _a.auth) == null ? void 0 : _b.token;
}, "get"),
cache: false,
// 注意:使用惰性 meta 工厂,避免在 i18n 尚未注入时提前求值导致无法翻译
meta: Object.assign(() => ({ type: "string", title: this.t("API Token"), sort: 980 }), {
title: "API Token",
sort: 980,
hasChildren: false
})
});
this.defineProperty("role", {
get: /* @__PURE__ */ __name(() => {
var _a, _b;
return (_b = (_a = this.api) == null ? void 0 : _a.auth) == null ? void 0 : _b.role;
}, "get"),
cache: false,
// 注意:使用惰性 meta 工厂,避免在 i18n 尚未注入时提前求值导致无法翻译
meta: Object.assign(() => ({ type: "string", title: this.t("Current role"), sort: 990 }), {
title: (0, import_utils.escapeT)("Current role"),
sort: 990,
hasChildren: false
})
});
this.defineProperty("urlSearchParams", {
// 不缓存,确保随 URL 变化实时生效
cache: false,
get: /* @__PURE__ */ __name(() => {
var _a;
const search = ((_a = this.location) == null ? void 0 : _a.search) || "";
const str = search.startsWith("?") ? search.slice(1) : search;
return import_qs.default.parse(str) || {};
}, "get"),
// 变量选择器中的元信息与动态子项
meta: Object.assign(
() => ({
type: "object",
title: this.t("URL search params"),
sort: 970,
disabled: /* @__PURE__ */ __name(() => {
var _a;
const search = ((_a = this.location) == null ? void 0 : _a.search) || "";
const str = search.startsWith("?") ? search.slice(1) : search;
const params = import_qs.default.parse(str) || {};
return Object.keys(params).length === 0;
}, "disabled"),
disabledReason: /* @__PURE__ */ __name(() => this.t(
"The value of this variable is derived from the query string of the page URL. This variable can only be used normally when the page has a query string."
), "disabledReason"),
properties: /* @__PURE__ */ __name(async () => {
var _a;
const search = ((_a = this.location) == null ? void 0 : _a.search) || "";
const str = search.startsWith("?") ? search.slice(1) : search;
const params = import_qs.default.parse(str) || {};
const props = {};
for (const key of Object.keys(params)) {
props[key] = { type: "string", title: key };
}
return props;
}, "properties")
}),
{
title: (0, import_utils.escapeT)("URL search params"),
sort: 970,
hasChildren: true
}
)
});
this.defineProperty("logger", {
get: /* @__PURE__ */ __name(() => {
return this.engine.logger.child({ module: "flow-engine" });
}, "get")
});
this.defineProperty("auth", {
get: /* @__PURE__ */ __name(() => ({
roleName: this.api.auth.role,
locale: this.api.auth.locale,
token: this.api.auth.token,
user: this.user
}), "get")
});
this.defineMethod("loadCSS", async (url) => {
return new Promise((resolve, reject) => {
const existingLink = document.querySelector(`link[href="${url}"]`);
if (existingLink) {
resolve(null);
return;
}
const link = document.createElement("link");
link.rel = "stylesheet";
link.href = url;
link.onload = () => resolve(null);
link.onerror = () => reject(new Error(`Failed to load CSS: ${url}`));
document.head.appendChild(link);
});
});
this.defineMethod("requireAsync", async (url) => {
return new Promise((resolve, reject) => {
if (!this.requirejs) {
reject(new Error("requirejs is not available"));
return;
}
this.requirejs(
[url],
(...args) => {
resolve(args[0]);
},
reject
);
});
});
this.defineMethod("createJSRunner", function(options) {
const runCtx = new FlowRunjsContext(this.createProxy());
return new import_JSRunner.JSRunner({
...options,
globals: {
ctx: runCtx,
window: (0, import_utils.createSafeWindow)(),
document: (0, import_utils.createSafeDocument)(),
...options == null ? void 0 : options.globals
}
});
});
this.defineMethod("copyToClipboard", async (text) => {
const content = String(text ?? "");
try {
if (typeof navigator !== "undefined" && navigator.clipboard && navigator.clipboard.writeText) {
await navigator.clipboard.writeText(content);
return;
}
} catch (e) {
}
return new Promise((resolve, reject) => {
try {
const ta = document.createElement("textarea");
ta.value = content;
ta.setAttribute("readonly", "");
ta.style.position = "fixed";
ta.style.top = "-9999px";
document.body.appendChild(ta);
ta.focus();
ta.select();
const ok = document.execCommand("copy");
document.body.removeChild(ta);
if (ok) resolve();
else reject(new Error("execCommand copy failed"));
} catch (err) {
reject(err);
}
});
});
this.defineMethod("buildServerContextParams", function(input) {
return (0, import_serverContextParams.buildServerContextParams)(this, input);
});
this.defineMethod("getAction", function(name) {
return this.engine.getAction(name);
});
this.defineMethod("getActions", function() {
return this.engine.getActions();
});
this.defineMethod("getEvents", function() {
return this.engine.getEvents();
});
this.defineMethod(
"runAction",
async function(actionName, params) {
const def = this.engine.getAction(actionName);
const ctx = this.createProxy();
if (!def) {
throw new Error(`Action '${actionName}' not found.`);
}
const defaultParams = await (0, import_utils.resolveDefaultParams)(def.defaultParams, ctx);
let combinedParams = { ...defaultParams || {}, ...params || {} };
let useRawParams = def.useRawParams;
if (typeof useRawParams === "function") {
useRawParams = await useRawParams(ctx);
}
if (!useRawParams) {
combinedParams = await ctx.resolveJsonTemplate(combinedParams);
}
if (!def.handler) {
throw new Error(`Action '${actionName}' has no handler.`);
}
return def.handler(ctx, combinedParams);
}
);
this.defineProperty("acl", {
get: /* @__PURE__ */ __name(() => {
const acl = new import_Acl.ACL(this.engine);
return acl;
}, "get")
});
this.defineMethod("aclCheck", function(params) {
return this.acl.aclCheck(params);
});
this.defineMethod("createResource", function(resourceType) {
return this.engine.createResource(resourceType, {
context: this.createProxy()
});
});
}
};
__name(_FlowEngineContext, "FlowEngineContext");
let FlowEngineContext = _FlowEngineContext;
const _FlowModelContext = class _FlowModelContext extends BaseFlowModelContext {
constructor(model) {
if (!(model instanceof import_models.FlowModel)) {
throw new Error("Invalid FlowModel instance");
}
super();
this.addDelegate(model.flowEngine.context);
this.defineMethod("onRefReady", (ref, cb, timeout) => {
this.engine.reactView.onRefReady(ref, cb, timeout);
});
this.defineMethod("runjs", async (code, variables, options) => {
const runner = this.createJSRunner({
globals: variables,
version: options == null ? void 0 : options.version
});
return runner.run(code);
});
this.defineProperty("model", {
value: model
});
this.defineProperty("ref", {
get: /* @__PURE__ */ __name(() => {
this.model["_refCreated"] = true;
return (0, import_react.createRef)();
}, "get")
});
this.defineMethod("openView", async function(uid, options) {
var _a, _b, _c, _d, _e, _f, _g;
const opts = { ...options };
if (opts.defineProperties || opts.defineMethod) {
opts.navigation = false;
}
let model2 = null;
model2 = await this.engine.loadModel({ uid });
if (!model2) {
model2 = this.engine.createModel({
uid,
// 注意: 新建的 model 应该使用 ${parentModel.uid}-xxx 形式的 uid
use: "PopupActionModel",
parentId: this.model.uid,
subType: "object",
subKey: uid,
stepParams: {
popupSettings: {
openView: {
...import_lodash.default.pick(opts, ["dataSourceKey", "collectionName", "associationName"])
}
}
}
});
await model2.save();
}
if ((_b = (_a = model2.getStepParams("popupSettings")) == null ? void 0 : _a.openView) == null ? void 0 : _b.dataSourceKey) {
model2.setStepParams("popupSettings", {
openView: {
...(_c = model2.getStepParams("popupSettings")) == null ? void 0 : _c.openView,
...import_lodash.default.pick(opts, ["dataSourceKey", "collectionName", "associationName"])
}
});
await model2.save();
}
const viewUid = (opts == null ? void 0 : opts.routeViewUid) ?? (opts == null ? void 0 : opts.viewUid) ?? (((_e = (_d = model2.stepParams) == null ? void 0 : _d.popupSettings) == null ? void 0 : _e.openView) ? model2.uid : this.model.uid);
const parentView = this.view;
const pendingType = (opts == null ? void 0 : opts.isMobileLayout) ? "embed" : (opts == null ? void 0 : opts.mode) || "drawer";
const pendingInputArgs = { ...opts, viewUid, navigation: opts.navigation };
pendingInputArgs.filterByTk = pendingInputArgs.filterByTk || ((_f = this.inputArgs) == null ? void 0 : _f.filterByTk);
pendingInputArgs.sourceId = pendingInputArgs.sourceId || ((_g = this.inputArgs) == null ? void 0 : _g.sourceId);
const pendingView = {
type: pendingType,
inputArgs: pendingInputArgs,
navigation: parentView == null ? void 0 : parentView.navigation,
preventClose: !!(opts == null ? void 0 : opts.preventClose),
engineCtx: this.engine.context
};
model2.context.defineProperty("view", { value: pendingView });
await model2.dispatchEvent("click", {
// navigation: false, // TODO: 路由模式有bug,不支持多层同样viewId的弹窗,因此这里默认先用false
// ...this.model?.['getInputArgs']?.(), // 避免部分关系字段信息丢失, 仿照 ClickableCollectionField 做法
...opts
});
model2.context.defineProperty("view", { value: void 0 });
});
this.defineMethod("getEvents", function() {
return this.model.getEvents();
});
this.defineMethod("getAction", function(name) {
return this.model.getAction(name);
});
this.defineMethod("getActions", function() {
return this.model.getActions();
});
this.defineMethod(
"runAction",
async function(actionName, params) {
const def = this.model.getAction(actionName);
const ctx = this.createProxy();
if (!def) {
throw new Error(`Action '${actionName}' not found.`);
}
const defaultParams = await (0, import_utils.resolveDefaultParams)(def.defaultParams, ctx);
let combinedParams = { ...defaultParams || {}, ...params || {} };
let useRawParams = def.useRawParams;
if (typeof useRawParams === "function") {
useRawParams = await useRawParams(ctx);
}
if (!useRawParams) {
combinedParams = await ctx.resolveJsonTemplate(combinedParams);
}
if (!def.handler) {
throw new Error(`Action '${actionName}' has no handler.`);
}
return def.handler(ctx, combinedParams);
}
);
}
};
__name(_FlowModelContext, "FlowModelContext");
let FlowModelContext = _FlowModelContext;
const _FlowForkModelContext = class _FlowForkModelContext extends BaseFlowModelContext {
constructor(master, fork) {
if (!(master instanceof import_models.FlowModel)) {
throw new Error("Invalid FlowModel instance");
}
super();
this.master = master;
this.fork = fork;
this.addDelegate(this.master.context);
this.defineMethod("onRefReady", (ref, cb, timeout) => {
this.engine.reactView.onRefReady(ref, cb, timeout);
});
this.defineProperty("model", {
get: /* @__PURE__ */ __name(() => this.fork, "get")
});
this.defineProperty("ref", {
get: /* @__PURE__ */ __name(() => {
this.fork["_refCreated"] = true;
return (0, import_react.createRef)();
}, "get")
});
this.defineMethod("runjs", async (code, variables, options) => {
const runner = this.createJSRunner({
globals: variables,
version: options == null ? void 0 : options.version
});
return runner.run(code);
});
}
};
__name(_FlowForkModelContext, "FlowForkModelContext");
let FlowForkModelContext = _FlowForkModelContext;
const _FlowRuntimeContext = class _FlowRuntimeContext extends BaseFlowModelContext {
constructor(model, flowKey, _mode = "runtime") {
super();
this.model = model;
this.flowKey = flowKey;
this._mode = _mode;
this.addDelegate(this.model.context);
this.defineMethod("getStepParams", (stepKey) => {
return model.getStepParams(flowKey, stepKey) || {};
});
this.defineMethod("setStepParams", (stepKey, params) => {
return model.setStepParams(flowKey, stepKey, params);
});
this.defineMethod("getStepResults", (stepKey) => {
return import_lodash.default.get(this.steps, [stepKey, "result"]);
});
this.defineMethod(
"useResource",
(className) => {
if (model.context.has("resource")) {
console.warn(`[FlowRuntimeContext] useResource - resource already defined in context: ${className}`);
return;
}
model.context.defineProperty("resource", {
get: /* @__PURE__ */ __name(() => {
return this.createResource(className);
}, "get")
});
if (!model["resource"]) {
model["resource"] = model.context.resource;
}
}
);
this.defineProperty("resource", {
get: /* @__PURE__ */ __name(() => model["resource"] || model.context["resource"], "get"),
cache: false
});
this.defineMethod("onRefReady", (ref, cb, timeout) => {
this.engine.reactView.onRefReady(ref, cb, timeout);
});
this.defineMethod("runjs", async (code, variables, options) => {
const runner = this.createJSRunner({
globals: variables,
version: options == null ? void 0 : options.version
});
return runner.run(code);
});
}
stepResults = {};
_getOwnProperty(key) {
if (this.mode === "runtime") {
return super._getOwnProperty(key, this.createProxy());
}
const options = this._props[key];
if (!options) return void 0;
if ("value" in options) {
return import_ContextPathProxy.ContextPathProxy.create()[key];
}
if (options.get) {
if (options.cache === false) {
return import_ContextPathProxy.ContextPathProxy.create()[key];
}
const cacheKey = options.observable ? "_observableCache" : "_cache";
if (!(key in this[cacheKey])) {
this[cacheKey][key] = import_ContextPathProxy.ContextPathProxy.create()[key];
}
return this[cacheKey][key];
}
return void 0;
}
exit() {
throw new import_utils.FlowExitException(this.flowKey, this.model.uid);
}
exitAll() {
throw new import_exceptions.FlowExitAllException(this.flowKey, this.model.uid);
}
get mode() {
return this._mode;
}
};
__name(_FlowRuntimeCo