@scenemesh/entity-engine
Version:
一个“元数据驱动 + 组件适配 + 动态关系 + 视图管线”式的实体引擎。以 **Model + View + FieldType + SuiteAdapter + DataSource** 为五大支点,统一 CRUD / 查询 / 引用管理 / 视图渲染 / 扩展注册,支持在运行期无侵入拼装出 **表单、网格、主从、看板、仪表盘、流程/树形视图** 等多形态界面。
1,604 lines (1,582 loc) • 168 kB
JavaScript
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
var _chunk4XLO6XC7js = require('./chunk-4XLO6XC7.js');
// src/modules/build-in/module.json
var module_default = {
name: "build-in-module",
version: "1.0.0",
description: "\u5185\u5EFA\u6A21\u5757",
provider: "Scenemesh Team",
dependencies: [],
url: "http://github.com/scenemesh"
};
// src/modules/build-in/config/config.ts
var models = [
{
name: "__default__",
title: "\u9ED8\u8BA4\u6A21\u578B",
description: "Default Model",
fields: []
},
{
name: "__config__",
title: "\u914D\u7F6E\u6A21\u578B",
description: "Config Model",
fields: [
{
name: "name",
title: "\u914D\u7F6E\u540D\u79F0",
description: "\u914D\u7F6E\u540D\u79F0",
type: "string",
isRequired: true,
searchable: true
},
{
name: "version",
title: "\u914D\u7F6E\u7248\u672C",
description: "\u914D\u7F6E\u7248\u672C",
type: "number",
isRequired: true,
searchable: false
},
{
name: "content",
title: "\u914D\u7F6E\u5185\u5BB9",
description: "\u914D\u7F6E\u5185\u5BB9",
type: "string",
isRequired: true,
searchable: false
}
]
},
{
name: "entity-change-log",
title: "\u5B9E\u4F53\u53D8\u66F4\u8BB0\u5F55",
description: "Entity Change Log",
fields: [
{
name: "modelName",
title: "Model Name",
description: "Model Name",
type: "string",
isRequired: true,
searchable: true
},
{
name: "objectId",
title: "Object ID",
description: "Object ID",
type: "string",
isRequired: true,
searchable: true
},
{
name: "changedBy",
title: "Changed By",
description: "Changed By",
type: "string",
isRequired: true,
searchable: true
},
{
name: "changeType",
title: "Change Type",
description: "Change Type",
type: "string",
isRequired: true,
searchable: true
},
{
name: "changeDetails",
title: "Change Details",
description: "Change Details",
type: "json",
isRequired: false,
searchable: false
}
]
},
{
name: "ee-base-user",
title: "\u7528\u6237\u6A21\u578B",
description: "Entity User Model",
fields: [
{
name: "userName",
title: "\u7528\u6237\u540D\u79F0",
description: "\u7528\u6237\u540D\u79F0",
type: "string",
isRequired: true,
searchable: true
},
{
name: "email",
title: "\u90AE\u7BB1",
description: "\u90AE\u7BB1\u5730\u5740",
type: "string",
isRequired: true,
searchable: true
},
{
name: "password",
title: "\u767B\u5F55\u5BC6\u7801",
description: "\u767B\u5F55\u5BC6\u7801",
type: "string",
isRequired: true
},
{
name: "avatar",
title: "\u5934\u50CF",
description: "\u5934\u50CF",
type: "binary",
isRequired: false,
searchable: false
}
]
}
];
var views = [
{
name: "entity-change-log-grid-view",
title: "\u5B9E\u4F53\u53D8\u66F4\u7F51\u683C\u89C6\u56FE",
description: "Entity Change Log Grid View",
modelName: "entity-change-log",
viewType: "grid",
items: [
{ name: "modelName", title: "Model Name", spanCols: 12 },
{ name: "objectId", title: "Object ID", spanCols: 12 },
{ name: "changedBy", title: "Changed By", spanCols: 12 },
{ name: "changeType", title: "Change Type", spanCols: 12 },
{ name: "changeDetails", title: "Change Details", spanCols: 12 }
]
},
{
name: "ee-base-user-grid-view",
title: "\u7528\u6237\u7F51\u683C\u89C6\u56FE",
description: "\u7528\u6237\u7F51\u683C\u89C6\u56FE",
modelName: "ee-base-user",
viewType: "grid",
items: [
{ name: "userName", title: "\u7528\u6237\u540D\u79F0", spanCols: 12 },
{ name: "email", title: "\u767B\u5F55\u90AE\u7BB1", spanCols: 12 },
{ name: "avatar", title: "\u5934\u50CF", widget: "image", spanCols: 12 }
]
},
{
name: "ee-base-user-form-view",
title: "\u7528\u6237\u7F51\u683C\u89C6\u56FE",
description: "\u7528\u6237\u7F51\u683C\u89C6\u56FE",
modelName: "ee-base-user",
viewType: "form",
items: [
{ name: "userName", title: "\u7528\u6237\u540D\u79F0", spanCols: 12 },
{ name: "email", title: "\u767B\u5F55\u90AE\u7BB1", spanCols: 12 },
{ name: "password", title: "\u767B\u5F55\u5BC6\u7801", widget: "password", spanCols: 12 },
{ name: "avatar", title: "\u5934\u50CF", widget: "image", spanCols: 12 }
]
}
];
// src/modules/build-in/buildin.module.ts
var servletHandler = {
path: "/ttt",
methods: ["GET", "POST"],
async handle(req, res) {
console.log("BuildinModule: handleRequest called");
res.write(new Response(`Hello from BuildinModule servlet! ${req.endpoint}`));
}
};
var BuildinModule = class {
constructor() {
this.info = module_default;
}
async setupConfig(args) {
console.log("BuildinModule: loadConfig called");
args.models.push(...models);
args.views.push(...views);
args.servlets.push(servletHandler);
}
async setupComponents(args) {
const authView = await Promise.resolve().then(() => _interopRequireWildcard(require("./auth.view-XE4MBUE7.js")));
args.views.push(new authView.default());
const mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./shell-settings-target-renderer-7N2CQ3VK.js")));
args.renderers.push(mod.default);
const menu = await Promise.resolve().then(() => _interopRequireWildcard(require("./shell-settings-menu-renderer-J6GZ7KUA.js")));
args.renderers.push(menu.default);
console.log("BuildinModule: loadComponents called");
}
async setupData(args) {
const demoUser = {
id: "3706a32d89d04423bc84cc1f9366881d",
modelName: "ee-base-user",
values: {
userName: "Demo User",
email: "demo@demo.com",
password: "fe01ce2a7fbac8fafaed7c982a04e229",
role: []
}
};
args.entities.push(demoUser);
}
};
// src/core/types/session.types.ts
var EntitySession = class {
constructor(sessionId, userInfo, update = () => {
}) {
this.sessionId = sessionId;
this.userInfo = userInfo;
this.update = update;
}
isAuthenticated() {
return !!this.userInfo;
}
};
// src/core/delegate/delegate.ts
var _zod = require('zod');
var EntityFieldDelegate = class {
constructor(field) {
this._field = field;
}
get name() {
return this._field.name;
}
get title() {
return this._field.title;
}
get type() {
return this._field.type;
}
get typeOptions() {
return this._field.typeOptions;
}
get description() {
return this._field.description;
}
get defaultValue() {
return this._field.defaultValue;
}
get isRequired() {
return _nullishCoalesce(this._field.isRequired, () => ( false));
}
get isPrimaryKey() {
return _nullishCoalesce(this._field.isPrimaryKey, () => ( false));
}
get isUnique() {
return _nullishCoalesce(this._field.isUnique, () => ( false));
}
get editable() {
return _nullishCoalesce(this._field.editable, () => ( true));
}
get searchable() {
return _nullishCoalesce(this._field.searchable, () => ( false));
}
get refModel() {
return this._field.refModel;
}
get refField() {
return this._field.refField;
}
get schema() {
return this._field.schema;
}
get order() {
return this._field.order;
}
};
var EntityModelDelegate = class {
constructor(model, typeRegistry) {
this._model = model;
this._typeRegistry = typeRegistry;
}
get name() {
return this._model.name;
}
get title() {
return this._model.title;
}
get description() {
return this._model.description;
}
get external() {
return this._model.external;
}
get externalConfig() {
return this._model.externalConfig;
}
isSupportFeature(feature) {
if (!this._model.external) return true;
const fs = _optionalChain([this, 'access', _2 => _2._model, 'access', _3 => _3.externalConfig, 'optionalAccess', _4 => _4.features]) || [];
console.log("@@@@@@@@@@@@@@ Supported features:", this._model.name, fs);
return fs.includes(feature);
}
findPrimaryKeyFields() {
return this._model.fields.filter((field) => field.isPrimaryKey);
}
findUniqueFields() {
return this._model.fields.filter((field) => field.isUnique);
}
findFieldByName(name) {
return this._model.fields.find((field) => field.name === name);
}
findFieldByTitle(title) {
return this._model.fields.find((field) => field.title === title);
}
findSearchableFields() {
return this._model.fields.filter((field) => field.searchable);
}
get schema() {
return _zod.z.object({
...this._model.fields.reduce((acc, field) => {
const fschema = this.getFieldSchema(field);
if (fschema) {
acc[field.name] = fschema;
}
return acc;
}, {})
});
}
getFieldSchema(field) {
if (field.schema) {
return field.schema;
}
const typer = this._typeRegistry.getFieldTyper(field.type);
if (typer) {
return typer.getDefaultSchema(field);
}
return void 0;
}
toSupplementedValues(input) {
const obj = {
...input,
...this._model.fields.reduce((acc, field) => {
if (!input[field.name]) {
acc[field.name] = input[field.name] || this.getFieldDefaultValue(field);
return acc;
} else {
return acc;
}
}, {})
};
return obj;
}
getFieldDefaultValue(field) {
if (field.defaultValue !== void 0) {
return field.defaultValue;
}
const typer = this._typeRegistry.getFieldTyper(field.type);
if (typer) {
return typer.getDefaultValue(field);
}
return void 0;
}
getQueryMeta() {
const itemMetas = [];
const searchableFields = this.fields.filter((f) => f.searchable);
searchableFields.forEach((field) => {
const meta = this.getFieldQueryItemMeta(field);
if (meta) {
itemMetas.push(meta);
}
});
return {
queryItemMetas: itemMetas
};
}
getFieldQueryItemMeta(field) {
if (!field.searchable) return void 0;
const operators = [];
const options = [];
const normalizeOptionItem = (item) => {
if (item == null) return void 0;
if (typeof item === "object") {
const value = "value" in item ? item.value : item;
const label = "label" in item ? item.label : String(value);
return { label, value };
}
return { label: String(item), value: item };
};
if (field.type === "string") {
operators.push(
"eq" /* EQ */,
"contains" /* CONTAINS */,
"startsWith" /* STARTS_WITH */,
"endsWith" /* ENDS_WITH */,
"isNotNull" /* IS_NOT_NULL */,
"isNull" /* IS_NULL */
);
}
if (field.type === "number") {
operators.push(
"eq" /* EQ */,
"gt" /* GT */,
"lt" /* LT */,
"isNotNull" /* IS_NOT_NULL */,
"isNull" /* IS_NULL */
);
}
if (field.type === "boolean") {
operators.push("eq" /* EQ */, "isNotNull" /* IS_NOT_NULL */, "isNull" /* IS_NULL */);
options.push({ label: "\u662F", value: true });
options.push({ label: "\u5426", value: false });
}
if (field.type === "date") {
operators.push(
"eq" /* EQ */,
"gt" /* GT */,
"lt" /* LT */,
"between" /* BETWEEN */,
"isNotNull" /* IS_NOT_NULL */,
"isNull" /* IS_NULL */
);
}
if (field.type === "enum") {
operators.push(
"eq" /* EQ */,
"ne" /* NE */,
"isNotNull" /* IS_NOT_NULL */,
"isNull" /* IS_NULL */
);
const raw = _optionalChain([field, 'access', _5 => _5.typeOptions, 'optionalAccess', _6 => _6.options]);
if (Array.isArray(raw)) {
for (const r of raw) {
const norm = normalizeOptionItem(r);
if (norm) options.push(norm);
}
} else {
const norm = normalizeOptionItem(raw);
if (norm) options.push(norm);
}
}
if (field.type === "array") {
operators.push(
"in" /* IN */,
"notIn" /* NOT_IN */,
"isNotNull" /* IS_NOT_NULL */,
"isNull" /* IS_NULL */
);
const raw = _optionalChain([field, 'access', _7 => _7.typeOptions, 'optionalAccess', _8 => _8.options]);
if (Array.isArray(raw)) {
for (const r of raw) {
const norm = normalizeOptionItem(r);
if (norm) options.push(norm);
}
}
}
if (operators.length > 0) {
return {
field,
operators,
options
};
}
return void 0;
}
get fields() {
return this._model.fields.map((field) => new EntityFieldDelegate(field));
}
};
var EntityViewFieldDelegate = class _EntityViewFieldDelegate {
constructor(field) {
this._field = field;
}
get name() {
return this._field.name;
}
get title() {
return this._field.title;
}
get description() {
return this._field.description;
}
get icon() {
return this._field.icon;
}
get widget() {
return this._field.widget;
}
get widgetOptions() {
return this._field.widgetOptions;
}
get width() {
return this._field.width;
}
get flex() {
return this._field.flex;
}
get spanCols() {
return this._field.spanCols;
}
get order() {
return this._field.order;
}
get fields() {
return _optionalChain([this, 'access', _9 => _9._field, 'access', _10 => _10.fields, 'optionalAccess', _11 => _11.map, 'call', _12 => _12((field) => new _EntityViewFieldDelegate(field))]);
}
get hiddenWhen() {
return this._field.hiddenWhen;
}
get showWhen() {
return this._field.showWhen;
}
get readOnlyWhen() {
return this._field.readOnlyWhen;
}
get disabledWhen() {
return this._field.disabledWhen;
}
get requiredWhen() {
return this._field.requiredWhen;
}
};
var EntityViewDelegate = class _EntityViewDelegate {
constructor(view, metaRegistry, typeRegistry) {
this._view = view;
this._metaRegistry = metaRegistry;
this._typeRegistry = typeRegistry;
}
get name() {
return this._view.name;
}
get title() {
return this._view.title;
}
get description() {
return this._view.description;
}
get modelName() {
return this._view.modelName;
}
get viewType() {
return this._view.viewType;
}
get density() {
return this._view.density;
}
get viewOptions() {
return this._view.viewOptions;
}
get items() {
return this._view.items.map((item) => new EntityViewFieldDelegate(item));
}
get hilites() {
return this._view.hilites;
}
get canEdit() {
return this._view.canEdit;
}
get canNew() {
return this._view.canNew;
}
get canDelete() {
return this._view.canDelete;
}
toSupplementedView(viewOptions) {
const view = {
...this._view,
...viewOptions && Object.keys(viewOptions).length > 0 ? { viewOptions } : {},
density: this._view.density || "medium",
items: this._view.items.map((field) => this.supplementField(field))
};
return new _EntityViewDelegate(view, this._metaRegistry, this._typeRegistry);
}
supplementField(item) {
if ("fields" in item) {
const panel = item;
return {
...panel,
fields: panel.fields.map((field) => this.supplementField(field))
};
} else {
const field = item;
const modelField = _optionalChain([this, 'access', _13 => _13._metaRegistry, 'access', _14 => _14.getModel, 'call', _15 => _15(this._view.modelName), 'optionalAccess', _16 => _16.findFieldByName, 'call', _17 => _17(field.name)]);
if (!modelField) {
return field;
} else {
return {
...field,
title: field.title || modelField.title,
description: field.description || modelField.description,
order: field.order || modelField.order || 0,
flex: field.flex || 0,
widget: this.getFieldWidget(field, modelField)
};
}
}
}
getFieldWidget(field, modelField) {
if (field.widget) {
return field.widget;
}
if (!modelField) {
return "none";
}
const typer = this._typeRegistry.getFieldTyper(modelField.type);
if (typer) {
return typer.getDefaultWidgetType(this._view.viewType);
}
switch (modelField.type) {
case "string":
return "textfield";
case "number":
return "number";
case "boolean":
return "switch";
case "date":
return "date";
case "enum":
case "array":
return "select";
case "one_to_many":
return "reference";
case "many_to_many":
return "reference";
case "many_to_one":
case "one_to_one":
return "select";
default:
return "none";
}
}
};
// src/core/delegate/meta.serializer.ts
var _zodtojsonschema = require('zod-to-json-schema');
var _zodfromjsonschema = require('zod-from-json-schema');
function serializeFieldSchema(schema) {
if (schema) {
try {
return _zodtojsonschema.zodToJsonSchema.call(void 0, schema);
} catch (e) {
console.error("Failed to serialize Zod schema to JSON schema:", e);
}
}
return void 0;
}
function deserializeFieldSchema(_data) {
if (_data) {
try {
return _zodfromjsonschema.convertJsonSchemaToZod.call(void 0, _data);
} catch (e) {
console.error("Failed to deserialize Zod schema from JSON schema:", e);
}
}
return void 0;
}
function serializeEntityModel(model) {
const safe = {
name: model.name,
title: model.title,
description: model.description,
external: model.external,
externalConfig: { features: _optionalChain([model, 'access', _18 => _18.externalConfig, 'optionalAccess', _19 => _19.features]) || [] },
fields: model.fields.map((field) => ({
name: field.name,
title: field.title,
type: field.type,
typeOptions: field.typeOptions,
description: field.description,
defaultValue: field.defaultValue,
isRequired: field.isRequired,
isPrimaryKey: field.isPrimaryKey,
isUnique: field.isUnique,
editable: field.editable,
searchable: field.searchable,
refModel: field.refModel,
refField: field.refField,
order: field.order,
// 添加 schemaSerialized 字段,保留原字段 schema 以便未来恢复
schemaSerialized: serializeFieldSchema(field.schema)
}))
};
return safe;
}
function deserializeEntityModel(json) {
if (!json) return void 0;
try {
const obj = JSON.parse(json);
if (!obj || typeof obj !== "object") return void 0;
if (typeof obj.name !== "string" || typeof obj.title !== "string") return void 0;
if (!Array.isArray(obj.fields)) return void 0;
const fields = obj.fields.filter((f) => f && typeof f === "object").map((f) => {
const {
name,
title,
type,
typeOptions,
description,
defaultValue,
isRequired,
isPrimaryKey,
isUnique,
editable,
searchable,
refModel,
refField,
order,
schemaSerialized
} = f;
if (typeof name !== "string" || typeof title !== "string" || typeof type !== "string") {
return void 0;
}
return {
name,
title,
type,
typeOptions,
description,
defaultValue,
isRequired,
isPrimaryKey,
isUnique,
editable,
searchable,
refModel,
refField,
order,
schema: deserializeFieldSchema(schemaSerialized)
};
}).filter(Boolean);
const model = {
name: obj.name,
title: obj.title,
external: obj.external,
externalConfig: obj.externalConfig,
description: typeof obj.description === "string" ? obj.description : void 0,
fields
};
return model;
} catch (e2) {
return void 0;
}
}
function serializeEntityView(view) {
if (!view) return void 0;
const VERSION = 1;
const cloneField = (field) => {
if (!field || typeof field !== "object") return void 0;
const {
name: name2,
title: title2,
description: description2,
icon,
widget,
widgetOptions,
width,
flex,
spanCols,
order,
fields,
hiddenWhen,
showWhen,
readOnlyWhen,
disabledWhen,
requiredWhen,
referenceView,
referenceComp
} = field;
if (typeof name2 !== "string") return void 0;
const safe2 = {
name: name2,
title: title2,
description: description2,
icon,
widget,
widgetOptions: widgetOptions ? JSON.parse(JSON.stringify(widgetOptions)) : void 0,
width,
flex,
spanCols,
order,
hiddenWhen,
showWhen,
readOnlyWhen,
disabledWhen,
requiredWhen,
referenceView,
referenceComp
};
if (Array.isArray(fields)) {
const child = fields.map((f) => cloneField(f)).filter(Boolean);
if (child.length > 0) safe2.fields = child;
}
return safe2;
};
const {
name,
title,
description,
modelName,
viewType,
viewOptions,
items,
hilites,
canEdit,
canNew,
canDelete,
density
} = view;
if (typeof name !== "string" || typeof title !== "string" || typeof modelName !== "string" || typeof viewType !== "string") {
throw new Error("Invalid IEntityView: missing required string fields");
}
const safeItems = Array.isArray(items) ? items.map((it) => cloneField(it)).filter(Boolean) : [];
const safe = {
__viewSerializerVersion: VERSION,
name,
title,
description,
modelName,
viewType,
viewOptions: viewOptions ? JSON.parse(JSON.stringify(viewOptions)) : void 0,
items: safeItems,
hilites: Array.isArray(hilites) ? hilites.filter((h) => h && typeof h === "object" && typeof h.when === "string").map((h) => ({ when: h.when, color: h.color })) : void 0,
canEdit,
canNew,
canDelete,
density
};
return safe;
}
function deserializeEntityView(json) {
if (!json) return void 0;
try {
const obj = JSON.parse(json);
if (!obj || typeof obj !== "object") return void 0;
const {
name,
title,
description,
modelName,
viewType,
viewOptions,
items,
hilites,
canEdit,
canNew,
canDelete,
density
} = obj;
if (typeof name !== "string" || typeof title !== "string" || typeof modelName !== "string" || typeof viewType !== "string") {
return void 0;
}
const reviveField = (field) => {
if (!field || typeof field !== "object") return void 0;
if (typeof field.name !== "string") return void 0;
const f = {
name: field.name,
title: typeof field.title === "string" ? field.title : void 0,
description: typeof field.description === "string" ? field.description : void 0,
icon: typeof field.icon === "string" ? field.icon : void 0,
widget: typeof field.widget === "string" ? field.widget : void 0,
widgetOptions: field.widgetOptions && typeof field.widgetOptions === "object" ? field.widgetOptions : void 0,
width: typeof field.width === "number" ? field.width : void 0,
flex: field.flex === 0 || field.flex === 1 ? field.flex : void 0,
spanCols: typeof field.spanCols === "number" ? field.spanCols : void 0,
order: typeof field.order === "number" ? field.order : void 0,
hiddenWhen: typeof field.hiddenWhen === "string" ? field.hiddenWhen : void 0,
showWhen: typeof field.showWhen === "string" ? field.showWhen : void 0,
readOnlyWhen: typeof field.readOnlyWhen === "string" ? field.readOnlyWhen : void 0,
disabledWhen: typeof field.disabledWhen === "string" ? field.disabledWhen : void 0,
requiredWhen: typeof field.requiredWhen === "string" ? field.requiredWhen : void 0,
referenceView: field.referenceView && typeof field.referenceView === "object" ? field.referenceView : void 0,
referenceComp: field.referenceComp && typeof field.referenceComp === "object" ? field.referenceComp : void 0
};
if (Array.isArray(field.fields)) {
const child = field.fields.map((c) => reviveField(c)).filter(Boolean);
if (child.length > 0) f.fields = child;
}
return f;
};
const safeItems = Array.isArray(items) ? items.map((it) => reviveField(it)).filter(Boolean) : [];
const safe = {
name,
title,
description: typeof description === "string" ? description : void 0,
modelName,
viewType,
viewOptions: viewOptions && typeof viewOptions === "object" ? viewOptions : void 0,
items: safeItems,
hilites: Array.isArray(hilites) ? hilites.filter((h) => h && typeof h.when === "string").map((h) => ({ when: h.when, color: h.color })) : void 0,
canEdit: typeof canEdit === "boolean" ? canEdit : void 0,
canNew: typeof canNew === "boolean" ? canNew : void 0,
canDelete: typeof canDelete === "boolean" ? canDelete : void 0,
density: density === "small" || density === "medium" || density === "large" ? density : void 0
};
return safe;
} catch (e3) {
return void 0;
}
}
// src/core/delegate/delegate.registry.ts
var EntityMetaRegistry = class {
constructor(typeRegistry, eventEmitter) {
this._models = /* @__PURE__ */ new Map();
this._views = /* @__PURE__ */ new Map();
this._typeRegistry = typeRegistry;
this._eventEmitter = eventEmitter;
}
getModel(name) {
return this._models.get(name);
}
get models() {
return Array.from(this._models.values());
}
get views() {
return Array.from(this._views.values());
}
getView(name) {
return this._views.get(name);
}
cleanup() {
this._models.clear();
this._views.clear();
}
findView(modelName, viewType, name) {
let _view = void 0;
if (name) {
_view = this._views.get(name);
}
if (!_view) {
const values = Array.from(this._views.values());
_view = values.find(
(view) => view.modelName === modelName && view.viewType === viewType
);
}
if (!_view) {
const m = this.getModel(modelName);
if (m) {
const _viewData = {
name: `${modelName}-${viewType}`,
title: `${m.title}`,
description: `${m.description}`,
modelName: m.name,
viewType,
density: "medium",
items: m.fields.map((field) => ({
name: field.name,
title: field.title,
description: field.description,
order: field.order || 0,
flex: 0
}))
};
_view = new EntityViewDelegate(_viewData, this, this._typeRegistry);
}
}
return _view;
}
registerModel(model) {
if (!model) {
throw new Error("Model cannot be undefined or null");
}
if (!model.name) {
throw new Error("Model must have a name");
}
this._models.set(model.name, new EntityModelDelegate(model, this._typeRegistry));
}
registerView(view) {
if (!view) {
throw new Error("View cannot be undefined or null");
}
if (!view.modelName || !view.name || !view.viewType) {
throw new Error("View must have modelName, name, and viewType defined");
}
this._views.set(view.name, new EntityViewDelegate(view, this, this._typeRegistry));
}
toPlainModelObject(model) {
return serializeEntityModel(model);
}
toPlainViewObject(view) {
return serializeEntityView(view.toSupplementedView());
}
updateOrRegisterByPlainObject(config) {
let ref = 0;
if (Array.isArray(config.models)) {
config.models.forEach((m) => {
const model = deserializeEntityModel(JSON.stringify(m));
if (model) {
if (this.getModel(model.name)) {
this._models.delete(model.name);
}
this.registerModel(model);
ref++;
}
});
}
if (Array.isArray(config.views)) {
config.views.forEach((v) => {
const view = deserializeEntityView(JSON.stringify(v));
console.log(`Deserialized view:`, view);
if (view) {
if (this.getView(view.name)) {
this._views.delete(view.name);
}
this.registerView(view);
ref++;
}
});
}
if (ref > 0) {
this._eventEmitter.emit({
name: "config.updated",
parameter: {
modelIds: _optionalChain([config, 'access', _20 => _20.models, 'optionalAccess', _21 => _21.map, 'call', _22 => _22((m) => m.name)]) || [],
viewIds: _optionalChain([config, 'access', _23 => _23.views, 'optionalAccess', _24 => _24.map, 'call', _25 => _25((v) => v.name)]) || []
}
});
}
}
toJSONString() {
const models2 = this.models.map((model) => serializeEntityModel(model));
const views2 = this.views.map((view) => serializeEntityView(view));
return JSON.stringify({ models: models2, views: views2 });
}
fromJSONString(json) {
if (!json) return;
try {
const obj = JSON.parse(json);
if (!obj || typeof obj !== "object") return;
const { models: models2, views: views2 } = obj;
this.cleanup();
if (Array.isArray(models2)) {
models2.forEach((m, idx) => {
try {
const model = deserializeEntityModel(JSON.stringify(m));
if (model) {
this.registerModel(model);
}
} catch (e) {
console.warn("[EntityMetaRegistry] Failed to load model index", idx, e);
}
});
}
if (Array.isArray(views2)) {
views2.forEach((v, idx) => {
try {
const view = deserializeEntityView(JSON.stringify(v));
if (view) {
if (view.modelName === "__default__" || this.getModel(view.modelName)) {
this.registerView(view);
} else {
console.warn(
`[EntityMetaRegistry] Skip view '${view.name}' because model '${view.modelName}' not found.`
);
}
}
} catch (e) {
console.warn("[EntityMetaRegistry] Failed to load view index", idx, e);
}
});
}
} catch (e) {
console.error("[EntityMetaRegistry] fromJSONString parse error:", e);
}
}
};
// src/services/api/trpc/vanilla-client.ts
var _superjson = require('superjson'); var _superjson2 = _interopRequireDefault(_superjson);
var _client = require('@trpc/client');
function createVanillaTrpcClient(url) {
return _client.createTRPCClient.call(void 0, {
links: [
_client.httpBatchLink.call(void 0, {
url,
transformer: _superjson2.default,
maxURLLength: 2048
// Set a safe max URL length
})
]
});
}
// src/lib/data/data-utils.ts
function convertRawEntityObject(eo) {
if (eo) {
const values = (() => {
if (!eo.values || typeof eo.values !== "object") {
return {};
}
if (Array.isArray(eo.values)) {
return {};
}
return eo.values;
})();
return {
id: eo.id,
modelName: eo.modelName,
isDeleted: eo.isDeleted,
createdAt: eo.createdAt,
updatedAt: eo.updatedAt,
values
// ...(typeof eo.valuesJson === 'object' && eo.valuesJson !== null ? eo.valuesJson : {})
};
}
return null;
}
function convertEntityTree(treeNode) {
if (!treeNode) return null;
return {
children: treeNode.children.map((item) => convertEntityTree(item)).filter((item) => item != null),
data: convertRawEntityObject(treeNode.data),
parentId: treeNode.parentId
};
}
// src/core/datasources/trpc.datasource.ts
var TRPCEntityObjectDataSource = class {
constructor(settings) {
this._serverUrl = "__";
this._settings = settings;
}
get __vanillaTrpcClient() {
const serverUrl = this._settings.getUrl("/trpc");
if (!this._vanillaTrpcClient || this._serverUrl !== serverUrl) {
console.log("Creating new TRPC client with URL:", serverUrl);
this._serverUrl = serverUrl;
this._vanillaTrpcClient = createVanillaTrpcClient(serverUrl);
}
return this._vanillaTrpcClient;
}
async findPlainConfig(input) {
return await this.__vanillaTrpcClient.model.findPlainConfig.query(input);
}
async findGroupedObjects(input) {
const result = await this.__vanillaTrpcClient.model.findGroupedObjects.query({
modelName: input.modelName,
groupBy: input.groupBy,
query: input.query,
reference: input.reference,
aggregations: input.aggregations,
groupSortBy: input.groupSortBy,
objectSortBy: input.objectSortBy
});
return {
groups: result.groups.map((group) => ({
key: group.key,
count: group.count,
objects: group.objects.map((obj) => convertRawEntityObject(obj)).filter((obj) => obj !== null && obj !== void 0),
aggregations: group.aggregations
})),
totalCount: result.totalCount
};
}
async findOne(input) {
const ret = await this.__vanillaTrpcClient.model.findObject.query({
id: input.id,
modelName: input.modelName
});
return Promise.resolve(convertRawEntityObject(ret));
}
async findMany(input) {
const query = input.query || {};
const ret = await this.__vanillaTrpcClient.model.listObjects.query({
modelName: input.modelName,
pagination: {
page: _nullishCoalesce(_optionalChain([query, 'optionalAccess', _26 => _26.pageIndex]), () => ( 1)),
pageSize: _nullishCoalesce(_optionalChain([query, 'optionalAccess', _27 => _27.pageSize]), () => ( 10))
},
reference: _optionalChain([query, 'optionalAccess', _28 => _28.references]),
filter: _optionalChain([query, 'optionalAccess', _29 => _29.filter]),
withAllReferences: input.withAllReferences
});
return Promise.resolve({
data: ret.data.map((obj) => convertRawEntityObject(obj)).filter((obj) => obj !== null && obj !== void 0),
count: ret.count
});
}
async findTreeObjects(input) {
const ret = await this.__vanillaTrpcClient.model.treeObjects.query(input);
if (Array.isArray(ret)) {
const nodes = [];
ret.forEach((node, index) => {
const cnode = convertEntityTree(node);
if (cnode) {
nodes.push(cnode);
}
});
return Promise.resolve(nodes);
} else {
return Promise.resolve(convertEntityTree(ret));
}
}
async findOneWithReferences(input) {
const ret = await this.__vanillaTrpcClient.model.findOneWithReferences.query({
objectId: input.id,
includeFieldNames: input.includeFieldNames
});
return Promise.resolve(convertRawEntityObject(ret));
}
async create(input) {
const values = _nullishCoalesce(input.data.values, () => ( {}));
const ret = await this.__vanillaTrpcClient.model.createObject.mutate({
id: input.data.id,
modelName: input.modelName,
values,
reference: input.reference
});
return Promise.resolve(convertRawEntityObject(ret));
}
async update(input) {
if (!input.data.values) {
throw new Error("\u66F4\u65B0\u5BF9\u8C61\u65F6 values \u4E0D\u80FD\u4E3A\u7A7A");
}
const ret = await this.__vanillaTrpcClient.model.updateObject.mutate({
id: input.id,
values: input.data.values
});
return Promise.resolve(ret ? true : false);
}
async updateValues(input) {
if (!input.values) {
throw new Error("\u66F4\u65B0\u5BF9\u8C61\u65F6 values \u4E0D\u80FD\u4E3A\u7A7A");
}
const ret = await this.__vanillaTrpcClient.model.updateValues.mutate({
id: input.id,
values: input.values
});
if (ret) {
return true;
}
return false;
}
async delete(input) {
const ret = await this.__vanillaTrpcClient.model.deleteObject.mutate({
id: input.id
});
return Promise.resolve(ret ? true : false);
}
async deleteMany(input) {
const ret = await this.__vanillaTrpcClient.model.deleteObjects.mutate({
ids: input.ids
});
return Promise.resolve(ret ? true : false);
}
async findCount(input) {
const ret = await this.__vanillaTrpcClient.model.countObjects.query({
modelName: input.modelName
});
return Promise.resolve(ret);
}
async findManyWithReferences(input) {
const ret = await this.__vanillaTrpcClient.model.listWithChildren.query({
modelName: input.modelName,
childFieldName: input.childrenFieldName,
pagination: {
page: _nullishCoalesce(_optionalChain([input, 'access', _30 => _30.query, 'optionalAccess', _31 => _31.pageIndex]), () => ( 1)),
pageSize: _nullishCoalesce(_optionalChain([input, 'access', _32 => _32.query, 'optionalAccess', _33 => _33.pageSize]), () => ( 10))
},
filter: _optionalChain([input, 'access', _34 => _34.query, 'optionalAccess', _35 => _35.filter])
});
return Promise.resolve({
data: ret.data.map(convertRawEntityObject).filter((obj) => obj !== null && obj !== void 0),
count: ret.count
});
}
async findReferences(input) {
const ret = await this.__vanillaTrpcClient.model.findObjectReferencesOM.query(input);
return Promise.resolve(ret);
}
async validate(input) {
return Promise.resolve(true);
}
async findReferencesCount(input) {
const ret = await this.__vanillaTrpcClient.model.findObjectReferencesCountOM.query(input);
return Promise.resolve(ret);
}
async createReference(input) {
const ret = await this.__vanillaTrpcClient.model.createObjectReference.mutate(input);
return Promise.resolve(ret);
}
async createReferences(input) {
const ret = await this.__vanillaTrpcClient.model.createObjectReferences.mutate(input);
return Promise.resolve(ret);
}
async deleteReference(input) {
const ret = await this.__vanillaTrpcClient.model.deleteObjectReference.mutate(input);
return Promise.resolve(ret);
}
async deleteReferences(input) {
const ret = await this.__vanillaTrpcClient.model.deleteObjectReferences.mutate(input);
return Promise.resolve(ret);
}
};
// src/core/datasources/datasource.factory.ts
var EntityDataSourceFactory = class {
constructor(settings) {
this._dataSource = null;
this._settings = settings;
}
getDataSource() {
if (!this._dataSource) {
this._dataSource = new TRPCEntityObjectDataSource(this._settings);
}
return this._dataSource;
}
};
// src/services/api/services/model.service.ts
var _client3 = require('@prisma/client');
var _cuid2 = require('@paralleldrive/cuid2');
// src/services/api/routers/utils/enhanced-query.ts
function buildForestFromFlatNodes(flatNodes) {
const nodeMap = /* @__PURE__ */ new Map();
const forest = [];
flatNodes.forEach((node) => {
const { parentId, ...data } = node;
nodeMap.set(node.id, {
data,
parentId,
children: []
});
});
nodeMap.forEach((node) => {
if (node.parentId) {
const parent = nodeMap.get(node.parentId);
if (parent) {
parent.children.push(node);
}
} else {
forest.push(node);
}
});
return forest;
}
async function getFullTree(prisma, fromModelName, fromFieldName, rootId) {
if (rootId) {
const flatNodesForSubtree = await prisma.$queryRaw`
WITH RECURSIVE SubTreeEdges AS (
-- 起始部分:从指定的 rootId 开始查找其直接子节点
SELECT "toObjectId", "fromObjectId"
FROM "EntityObjectReference"
WHERE "fromObjectId" = ${rootId}
AND "fromModelName" = ${fromModelName}
AND "fromFieldName" = ${fromFieldName}
UNION ALL
-- 递归部分:继续查找子孙节点
SELECT eor."toObjectId", eor."fromObjectId"
FROM "EntityObjectReference" eor
JOIN SubTreeEdges ste ON eor."fromObjectId" = ste."toObjectId"
WHERE eor."fromModelName" = ${fromModelName}
AND eor."fromFieldName" = ${fromFieldName}
),
NodesInSubTree AS (
-- 将根节点自己和所有子孙节点的ID合并
SELECT ${rootId} AS id
UNION ALL
SELECT "toObjectId" FROM SubTreeEdges
)
-- 查询这些节点的信息及其父节点ID
SELECT
eo.*,
ste."fromObjectId" as "parentId"
FROM NodesInSubTree nist
JOIN "EntityObject" eo ON nist.id = eo.id
LEFT JOIN SubTreeEdges ste ON nist.id = ste."toObjectId";
`;
const forest = buildForestFromFlatNodes(flatNodesForSubtree);
return forest.length > 0 ? forest[0] : null;
} else {
const flatNodesForForest = await prisma.$queryRaw`
WITH RECURSIVE DescendantEdges AS (
SELECT "toObjectId", "fromObjectId" FROM "EntityObjectReference"
WHERE "fromModelName" = ${fromModelName} AND "fromFieldName" = ${fromFieldName}
UNION ALL
SELECT eor."toObjectId", eor."fromObjectId" FROM "EntityObjectReference" eor
JOIN DescendantEdges de ON eor."fromObjectId" = de."toObjectId"
WHERE eor."fromModelName" = ${fromModelName} AND eor."fromFieldName" = ${fromFieldName}
),
NodesInConnectedTrees AS (
SELECT "toObjectId" AS id FROM DescendantEdges
UNION
SELECT "fromObjectId" AS id FROM DescendantEdges
)
SELECT eo.*, de."fromObjectId" AS "parentId"
FROM NodesInConnectedTrees nict JOIN "EntityObject" eo ON nict.id = eo.id
LEFT JOIN (SELECT DISTINCT "toObjectId", "fromObjectId" FROM DescendantEdges) AS de ON nict.id = de."toObjectId"
UNION ALL
SELECT eo.*, NULL AS "parentId"
FROM "EntityObject" eo
WHERE eo."modelName" = ${fromModelName}
AND NOT EXISTS (
SELECT 1 FROM "EntityObjectReference" eor
WHERE eor."toObjectId" = eo.id AND eor."fromModelName" = ${fromModelName} AND eor."fromFieldName" = ${fromFieldName}
)
AND NOT EXISTS (
SELECT 1 FROM "EntityObjectReference" eor
WHERE eor."fromObjectId" = eo.id AND eor."fromModelName" = ${fromModelName} AND eor."fromFieldName" = ${fromFieldName}
);
`;
return buildForestFromFlatNodes(flatNodesForForest);
}
}
function buildHierarchyInValues(flatList) {
if (!flatList || !Array.isArray(flatList) || flatList.length === 0) {
console.error(
"[buildHierarchyInValues] Error: Input 'flatList' is empty or invalid. Returning null."
);
return null;
}
const nodeMap = /* @__PURE__ */ new Map();
let root = null;
flatList.forEach((item) => {
if (!item || typeof item.id === "undefined") {
console.warn(
"[buildHierarchyInValues] Warning: Skipping invalid item in flatList:",
item
);
return;
}
const initialValues = typeof item.values === "object" && item.values !== null ? item.values : {};
const node = {
id: item.id,
modelName: item.modelName,
values: initialValues,
isDeleted: item.isDeleted
};
nodeMap.set(node.id, node);
});
flatList.forEach((item) => {
if (!item || typeof item.toid === "undefined") return;
const parentId = item.fromid;
const childId = item.toid;
const relationField = item.viafield;
if (!parentId || parentId === null) {
if (root === null) {
root = nodeMap.get(childId);
console.warn(
`[buildHierarchyInValues] Warning: root node found. Using '${childId}' as the root.`
);
} else {
console.warn(
`[buildHierarchyInValues] Warning: Multiple root nodes found. Using '${root.id}' as the root. Another root found: '${childId}'.`
);
}
return;
}
if (relationField && nodeMap.has(parentId) && nodeMap.has(childId)) {
const parentNode = nodeMap.get(parentId);
const childNode = nodeMap.get(childId);
if (!parentNode.values[relationField]) {
parentNode.values[relationField] = [];
}
if (Array.isArray(parentNode.values[relationField])) {
parentNode.values[relationField].push(childNode);
} else {
parentNode.values[relationField] = childNode;
}
} else if (relationField) {
console.warn(
`[buildHierarchyInValues] Warning: Could not form relationship for item. Missing parent or child in nodeMap.`,
item
);
}
});
if (root === null) {
console.error(
"[buildHierarchyInValues] Error: Failed to determine a root node from the provided data. Make sure at least one item has a null 'fromId'."
);
}
return root;
}
async function getDeepEntityFirstLevelFilter(prisma, startId, fieldNamesToInclude) {
let filterClause = _client3.Prisma.empty;
if (fieldNamesToInclude && fieldNamesToInclude.length > 0) {
filterClause = _client3.Prisma.sql`
AND (
eg.depth > 0 -- 如果深度大于0 (即非第一层),则条件为真,允许通行
OR
ref."fromFieldName" IN (${_client3.Prisma.join(fieldNamesToInclude)}) -- 否则 (在第一层),检查fieldName
)
`;
}
const flatList = await prisma.$queryRaw(
_client3.Prisma.sql`
WITH RECURSIVE EntityGraph AS (
SELECT
eo.id AS toId,
NULL::VARCHAR AS fromId,
NULL::VARCHAR AS viaField,
0 AS depth
FROM
"EntityObject" AS eo
WHERE
eo.id = ${startId}
UNION ALL
SELECT
ref."toObjectId" AS toId,
ref."fromObjectId" AS fromId,
ref."fromFieldName" AS viaField,
eg.depth + 1
FROM
"EntityObjectReference" AS ref
JOIN
EntityGraph AS eg ON ref."fromObjectId" = eg.toId
WHERE
eg.depth < 10
${filterClause} -- <-- 在这里注入新的、深度感知的过滤条件
)
SELECT
graph.toId,
graph.fromId,
graph.viaField,
graph.depth,
eo.id,
eo."modelName",
eo.values,
eo."isDeleted"
FROM
EntityGraph AS graph
JOIN
"EntityObject" AS eo ON graph.toId = eo.id;
`
);
if (!Array.isArray(flatList) || flatList.length === 0) {
return null;
}
const root = buildHierarchyInValues(flatList);
return root;
}
// src/services/api/services/mode.external.service.ts
var _pg = require('pg');
var _poolMap;
var ModelExternalPoolService = class {
constructor() {
_chunk4XLO6XC7js.__privateAdd.call(void 0, this, _poolMap);
_chunk4XLO6XC7js.__privateSet.call(void 0, this, _poolMap, /* @__PURE__ */ new Map());
}
async getPool(url) {
try {
if (!_chunk4XLO6XC7js.__privateGet.call(void 0, this, _poolMap).has(url)) {
const pool = new (0, _pg.Pool)({ connectionString: url });
await pool.connect();
_chunk4XLO6XC7js.__privateGet.call(void 0, this, _poolMap).set(url, pool);
}
return Promise.resolve(_chunk4XLO6XC7js.__privateGet.call(void 0, this, _poolMap).get(url));
} catch (error) {
console.error("Error getting database pool:", error);
return null;
}
}
};
_poolMap = new WeakMap();
var modelExternalPoolService = new ModelExternalPoolService();
async function externalfindObjectLogic(engine, input) {
const model = engine.metaRegistry.getModel(input.modelName);
if (!model) {
throw new Error(`Model not found: ${input.modelName}`);
}
const externalConfig = model.externalConfig;
if (!externalConfig) {
throw new Error(`External config not found for model: ${input.modelName}`);
}
const pool = await modelExternalPoolService.getPool(externalConfig.url);
if (!pool) {
throw new Error("Failed to acquire external database pool");
}
const result = await pool.query(
`SELECT * FROM "${externalConfig.tableName}" WHERE "${_optionalChain([externalConfig, 'access', _36 => _36.mappings, 'access', _37 => _37.find, 'call', _38 => _38((m) => m.local === "$$id"), 'optionalAccess', _39 => _39.remote])}" = $1 LIMIT 1`,
[input.id]
);
if (result && result.rows && result.rows.length > 0) {
return convertRowToEntityObject(result.rows[0], model, externalConfig);
}
return null;
}
async function externalListObjectsLogic(engine, input) {
const { modelName, pagination, reference, filter } = input;
if (reference) {
throw new Error("External model listing with reference filter is not supported yet.");
}
const skip = ((_nullishCoalesce(_optionalChain([pagination, 'optionalAccess', _40 => _40.page]), () => ( 1))) - 1) * (_nullishCoalesce(_optionalChain([