@stalfh233/omc-fake-platform 0.0.0-stage → 0.4.39
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/app.d.ts +3 -0
- package/dist/app.js +44 -0
- package/dist/b2-registration.d.ts +2 -0
- package/dist/b2-registration.js +619 -0
- package/dist/businessrule.d.ts +3 -0
- package/dist/businessrule.js +241 -0
- package/dist/datarule.d.ts +2 -0
- package/dist/datarule.js +71 -0
- package/dist/dictionary.d.ts +2 -0
- package/dist/dictionary.js +107 -0
- package/dist/environment.d.ts +6 -0
- package/dist/environment.js +29 -0
- package/dist/field.d.ts +3 -0
- package/dist/field.js +166 -0
- package/dist/form.d.ts +3 -0
- package/dist/form.js +100 -0
- package/dist/http-server.d.ts +8 -0
- package/dist/http-server.js +64 -0
- package/dist/index.d.ts +54 -0
- package/dist/index.js +120 -0
- package/dist/list-view.d.ts +3 -0
- package/dist/list-view.js +288 -0
- package/dist/model.d.ts +3 -0
- package/dist/model.js +135 -0
- package/dist/online-js.d.ts +3 -0
- package/dist/online-js.js +17 -0
- package/dist/report.d.ts +2 -0
- package/dist/report.js +252 -0
- package/dist/routes.d.ts +2 -0
- package/dist/routes.js +46 -0
- package/dist/rule-lifecycle.d.ts +7 -0
- package/dist/rule-lifecycle.js +36 -0
- package/dist/runtime-data.d.ts +2 -0
- package/dist/runtime-data.js +366 -0
- package/dist/state.d.ts +400 -0
- package/dist/state.js +66 -0
- package/dist/workflow.d.ts +39 -0
- package/dist/workflow.js +363 -0
- package/package.json +24 -4
package/dist/model.js
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { relationTargetOf } from "omc-core/relation-shape";
|
|
2
|
+
import { MODEL_REFERENCED_DELETE_ERRCODE } from "omc-core/wire-facts";
|
|
3
|
+
import { businessRefusal, NOT_HANDLED } from "./state.js";
|
|
4
|
+
/** model-management lane: app tree, model CRUD, physical delete. Twin of src/lanes/model.ts. */
|
|
5
|
+
export const modelRoute = (ctx, input) => {
|
|
6
|
+
const q = input.query ?? {};
|
|
7
|
+
const body = (input.body ?? {});
|
|
8
|
+
switch (input.path) {
|
|
9
|
+
case "/api/api/app/apppackage/trees": {
|
|
10
|
+
// Live fidelity (ticket 68): the tree row id is the AppFunction id, not
|
|
11
|
+
// the biz-model record id; appCode filters the tree, treeHidden models
|
|
12
|
+
// keep a record but no tree node. Ticket 83: rows carry parentId (live
|
|
13
|
+
// AppFunctionModel shape; bizmodels/update requires it) and the node
|
|
14
|
+
// display name comes from nodeName (the menu node is renamed
|
|
15
|
+
// independently of the schema record).
|
|
16
|
+
const appCode = q.appCode === undefined ? undefined : String(q.appCode);
|
|
17
|
+
// Live 8.6.26 fidelity (2026-09-17): the tree is NESTED — a Folder row
|
|
18
|
+
// carrying its BizModel children — not a flat list. The environment lane
|
|
19
|
+
// used a top-level map and silently dropped every model, so a live
|
|
20
|
+
// discover_environment with applicationCode returned no models. Consumers
|
|
21
|
+
// must flattenTreeRows (as resolveModelTreeNode already does); the fake
|
|
22
|
+
// must nest so a regression cannot pass.
|
|
23
|
+
const children = [...ctx.state.models.values()]
|
|
24
|
+
.filter((model) => !model.treeHidden && (appCode === undefined || (model.appCode ?? "test") === appCode))
|
|
25
|
+
.map((model) => ({ id: model.id, type: "BizModel", code: model.code, name: model.nodeName ?? model.name, parentId: "folder-1" }));
|
|
26
|
+
return [{ id: "folder-1", type: "FOLDER", code: "general", name: "General", children }];
|
|
27
|
+
}
|
|
28
|
+
case "/api/api/app/bizmodels/list_schema":
|
|
29
|
+
return [...ctx.state.models.values()].map((model) => ({ id: model.recordId, schemaCode: model.code, name: model.name }));
|
|
30
|
+
case "/api/api/app/bizmodels/create": {
|
|
31
|
+
const code = String(body.bizSchemaCode ?? body.code);
|
|
32
|
+
const n = ctx.state.models.size + 1;
|
|
33
|
+
ctx.state.models.set(code, {
|
|
34
|
+
id: `model-${n}-fn`,
|
|
35
|
+
recordId: `model-${n}-rec`,
|
|
36
|
+
code,
|
|
37
|
+
name: String(body.name ?? code),
|
|
38
|
+
appCode: String(body.applicationCode ?? body.appCode ?? "test"),
|
|
39
|
+
});
|
|
40
|
+
// Live fidelity (ticket 42): bizmodels/create seeds NO form — the model
|
|
41
|
+
// has no h_biz_sheet row until the form is created (bizsheet/create, or
|
|
42
|
+
// form.draft's scaffold-on-absent path). Do not pre-seed a sheet here.
|
|
43
|
+
return { schemaCode: code };
|
|
44
|
+
}
|
|
45
|
+
case "/api/api/app/apppackage/physically_delete": {
|
|
46
|
+
const rows = Array.isArray(input.body) ? input.body : [];
|
|
47
|
+
for (const row of rows) {
|
|
48
|
+
if (row.type === undefined || row.type === null || row.type === "") {
|
|
49
|
+
ctx.state.apps.delete(String(row.code));
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
const code = String(row.code);
|
|
53
|
+
// deleteFunctions semantics (ticket 23): a model referenced by
|
|
54
|
+
// another model's relation field cannot be deleted. Live: the sync
|
|
55
|
+
// face answers errcode 0 and the async dispatcher fails with
|
|
56
|
+
// ServiceException "xxx被模型 yyy 引用,不能删除"
|
|
57
|
+
// (AppIntegrationFacadeImpl.deleteFunctions:2201); the fake surfaces
|
|
58
|
+
// the check synchronously (MODEL_REFERENCED_DELETE_ERRCODE stands for
|
|
59
|
+
// the ServiceException envelope family) so the blocker and the
|
|
60
|
+
// referencing list are visible even when a caller bypasses the tool
|
|
61
|
+
// precheck. The live per-column async cascade (3-4s/column) is not
|
|
62
|
+
// simulated — the fake removes the model synchronously.
|
|
63
|
+
const referencers = [
|
|
64
|
+
...new Set([...ctx.state.fields.entries()]
|
|
65
|
+
.filter(([key, field]) => !key.startsWith(`${code}#`) && relationTargetOf(field) === code)
|
|
66
|
+
.map(([key]) => key.split("#")[0])),
|
|
67
|
+
];
|
|
68
|
+
if (referencers.length > 0)
|
|
69
|
+
return businessRefusal(MODEL_REFERENCED_DELETE_ERRCODE, `${code}被模型 ${referencers.join(",")} 引用,不能删除`);
|
|
70
|
+
// Ticket 68 live fidelity: physically_delete resolves each row id as an
|
|
71
|
+
// AppFunction id (removeBizModel → getAppFunction(id)); a biz-model
|
|
72
|
+
// record id is refused with 601003 业务模型不存在.
|
|
73
|
+
const model = ctx.state.models.get(code);
|
|
74
|
+
if (model && row.id !== model.id)
|
|
75
|
+
return businessRefusal(601003, "业务模型不存在");
|
|
76
|
+
ctx.state.models.delete(code);
|
|
77
|
+
ctx.state.sheets.delete(code);
|
|
78
|
+
// The cascade drops the model's own bizproperty rows too — without
|
|
79
|
+
// this cleanup a deleted referencing model would keep blocking the
|
|
80
|
+
// referenced model's delete (dependency-inverted chains must pass).
|
|
81
|
+
for (const key of [...ctx.state.fields.keys()])
|
|
82
|
+
if (key.startsWith(`${code}#`))
|
|
83
|
+
ctx.state.fields.delete(key);
|
|
84
|
+
}
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
case "/api/api/app/bizmodels/exits_bizschema":
|
|
88
|
+
return ctx.state.models.has(q.schemaCode);
|
|
89
|
+
case "/api/api/app/bizmodels/get_summary":
|
|
90
|
+
// BizSchemaController.get_summary: an absent schema answers "" (ok), an
|
|
91
|
+
// existing one returns its summary string.
|
|
92
|
+
return ctx.state.models.get(q.schemaCode)?.summary ?? "";
|
|
93
|
+
case "/api/api/app/bizmodels/update_summary": {
|
|
94
|
+
// BizSchemaController.updateSummary: non-empty summary required
|
|
95
|
+
// (validateNotEmpty) and a missing schema answers the
|
|
96
|
+
// BIZ_SCHEMA_NOT_PUBLISHED errcode (ErrorCode.java:194 → 300014).
|
|
97
|
+
const schemaCode = String(body.schemaCode ?? "");
|
|
98
|
+
if (!ctx.state.models.has(schemaCode))
|
|
99
|
+
return businessRefusal(300014, "数据模型未发布");
|
|
100
|
+
const model = ctx.state.models.get(schemaCode);
|
|
101
|
+
model.summary = String(body.summary ?? "");
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
case "/api/api/app/bizmodels/get_all": {
|
|
105
|
+
const model = ctx.state.models.get(q.schemaCode);
|
|
106
|
+
return model ? { id: model.recordId, name: model.name, modelType: "LIST" } : null;
|
|
107
|
+
}
|
|
108
|
+
case "/api/api/app/bizmodels/update": {
|
|
109
|
+
// Ticket 83 (source-pinned BizSchemaController.update :266-305): the
|
|
110
|
+
// endpoint patches the AppFunction MENU NODE — bizSchemaCode, id, name,
|
|
111
|
+
// parentId are all validateNotEmpty-required; the schema RECORD is not
|
|
112
|
+
// migrated (get_all keeps the original name/type per probe evidence),
|
|
113
|
+
// so the rename lands on nodeName only.
|
|
114
|
+
const schemaCode = String(body.bizSchemaCode ?? body.schemaCode ?? "");
|
|
115
|
+
const model = ctx.state.models.get(schemaCode);
|
|
116
|
+
if (!model)
|
|
117
|
+
return businessRefusal(300014, "数据模型未发布");
|
|
118
|
+
const nodeId = String(body.id ?? "");
|
|
119
|
+
const name = String(body.name ?? "");
|
|
120
|
+
const parentId = String(body.parentId ?? "");
|
|
121
|
+
if (!nodeId)
|
|
122
|
+
return businessRefusal(10005, "id不能为空");
|
|
123
|
+
if (!name)
|
|
124
|
+
return businessRefusal(10005, "名称不能为空");
|
|
125
|
+
if (!parentId)
|
|
126
|
+
return businessRefusal(10005, "父id不可为空");
|
|
127
|
+
if (nodeId !== model.id)
|
|
128
|
+
return businessRefusal(10005, `id不是模型 ${schemaCode} 的应用树节点`);
|
|
129
|
+
model.nodeName = name;
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
default:
|
|
133
|
+
return NOT_HANDLED;
|
|
134
|
+
}
|
|
135
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { NOT_HANDLED } from "./state.js";
|
|
2
|
+
/** online-js lane: programming compile/get_source/publish. Twin of src/lanes/online-js.ts. */
|
|
3
|
+
export const onlineJsRoute = (ctx, input) => {
|
|
4
|
+
const q = input.query ?? {};
|
|
5
|
+
const body = (input.body ?? {});
|
|
6
|
+
switch (input.path) {
|
|
7
|
+
case "/api/api/programming/compile":
|
|
8
|
+
return { compiled: true };
|
|
9
|
+
case "/api/api/programming/get_source":
|
|
10
|
+
return ctx.state.onlineJs.get(`${q.schemaCode}#${q.sheetCode}`) ?? null;
|
|
11
|
+
case "/api/api/programming/publish":
|
|
12
|
+
ctx.state.onlineJs.set(`${body.schemaCode}#${body.sheetCode}`, String(body.source));
|
|
13
|
+
return null;
|
|
14
|
+
default:
|
|
15
|
+
return NOT_HANDLED;
|
|
16
|
+
}
|
|
17
|
+
};
|
package/dist/report.d.ts
ADDED
package/dist/report.js
ADDED
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import { businessRefusal, NOT_HANDLED, rawResponse } from "./state.js";
|
|
2
|
+
/**
|
|
3
|
+
* R1-report fake. Twin of src/lanes/report.ts: the platform channel
|
|
4
|
+
* (`/api/api/report/*`, errcode envelope) owns the report page; the BI channel
|
|
5
|
+
* (`/dashboard/v1/*`, `{data}` / `{errorCode}` envelope) owns the dashboard and
|
|
6
|
+
* charts. Fidelity notes matching live (aozhe tenant):
|
|
7
|
+
* - a BI call with no in-body `config` returns `{data:true}` but mutates
|
|
8
|
+
* nothing (silent no-op);
|
|
9
|
+
* - an absent dashboard answers `errorCode:"dashboard.not.exist"`;
|
|
10
|
+
* - a report tree reports a page's charts from its BI dashboard.
|
|
11
|
+
*/
|
|
12
|
+
function reportTree(ctx, appCode) {
|
|
13
|
+
const pages = [...ctx.state.reportPages.values()].filter((page) => !appCode || page.appCode === appCode);
|
|
14
|
+
const byApp = new Map();
|
|
15
|
+
for (const page of pages) {
|
|
16
|
+
const list = byApp.get(page.appCode) ?? [];
|
|
17
|
+
list.push(page);
|
|
18
|
+
byApp.set(page.appCode, list);
|
|
19
|
+
}
|
|
20
|
+
return [...byApp.entries()].map(([app, appPages]) => ({
|
|
21
|
+
code: app,
|
|
22
|
+
appFunctionList: appPages.map((page) => ({
|
|
23
|
+
code: page.code,
|
|
24
|
+
name: page.name,
|
|
25
|
+
appCode: page.appCode,
|
|
26
|
+
type: "Report",
|
|
27
|
+
reportObjectId: page.id,
|
|
28
|
+
appReportChartList: (ctx.state.biDashboards.get(page.id)?.charts ?? []).map((chart) => ({
|
|
29
|
+
uuid: chart.uuid,
|
|
30
|
+
title: chart.title,
|
|
31
|
+
type: chart.type,
|
|
32
|
+
objectId: page.id,
|
|
33
|
+
})),
|
|
34
|
+
})),
|
|
35
|
+
}));
|
|
36
|
+
}
|
|
37
|
+
function hasConfig(body) {
|
|
38
|
+
const config = body.config;
|
|
39
|
+
return typeof config === "object" && config !== null;
|
|
40
|
+
}
|
|
41
|
+
/** BI error envelope (`{errorCode,...}`), returned verbatim with HTTP 200. */
|
|
42
|
+
function biError(errorCode, errorMessage) {
|
|
43
|
+
return rawResponse({ errorCode, errorMessage, errorType: "BIZ" });
|
|
44
|
+
}
|
|
45
|
+
function biData(data) {
|
|
46
|
+
return rawResponse({ data });
|
|
47
|
+
}
|
|
48
|
+
function biNoop() {
|
|
49
|
+
return biData(true);
|
|
50
|
+
}
|
|
51
|
+
export const reportRoute = (ctx, input) => {
|
|
52
|
+
const q = input.query ?? {};
|
|
53
|
+
const body = (input.body ?? {});
|
|
54
|
+
switch (input.path) {
|
|
55
|
+
// ---- platform channel ----
|
|
56
|
+
case "/api/api/app/folders/queryReportChartTree":
|
|
57
|
+
return reportTree(ctx);
|
|
58
|
+
case "/api/api/runtime/app/queryReportChartTreeByApp":
|
|
59
|
+
return reportTree(ctx, q.appCode);
|
|
60
|
+
case "/api/api/report/get": {
|
|
61
|
+
const page = ctx.state.reportPages.get(q.code);
|
|
62
|
+
if (!page)
|
|
63
|
+
return businessRefusal(302035, "报表不存在!");
|
|
64
|
+
// Live fidelity: report/get omits a top-level `parentId`; the immediate
|
|
65
|
+
// folder is the LAST folderList entry. The tool must derive parentId from
|
|
66
|
+
// it (report/update 500s without one).
|
|
67
|
+
const { parentId, ...rest } = page;
|
|
68
|
+
return { ...rest, reportObjectId: page.id, folderList: [{ id: parentId, type: "Folder" }] };
|
|
69
|
+
}
|
|
70
|
+
case "/api/api/report/create": {
|
|
71
|
+
const code = String(body.code ?? "");
|
|
72
|
+
if (!code)
|
|
73
|
+
return businessRefusal(50000, "code 不能为空");
|
|
74
|
+
if (ctx.state.reportPages.has(code))
|
|
75
|
+
return businessRefusal(50000, "编码重复");
|
|
76
|
+
const page = {
|
|
77
|
+
id: `report-${ctx.state.reportPages.size + 1}`,
|
|
78
|
+
code,
|
|
79
|
+
name: String(body.name ?? code),
|
|
80
|
+
appCode: String(body.appCode ?? ""),
|
|
81
|
+
parentId: String(body.parentId ?? ""),
|
|
82
|
+
icon: String(body.icon ?? "h-icon-all-Report"),
|
|
83
|
+
pcAble: body.pcAble !== false,
|
|
84
|
+
mobileAble: body.mobileAble !== false,
|
|
85
|
+
name_i18n: typeof body.name_i18n === "string" ? body.name_i18n : JSON.stringify(body.name_i18n ?? {}),
|
|
86
|
+
};
|
|
87
|
+
ctx.state.reportPages.set(code, page);
|
|
88
|
+
return { ...page, reportObjectId: page.id };
|
|
89
|
+
}
|
|
90
|
+
case "/api/api/report/update": {
|
|
91
|
+
const id = String(body.id ?? "");
|
|
92
|
+
const page = [...ctx.state.reportPages.values()].find((entry) => entry.id === id);
|
|
93
|
+
if (!page)
|
|
94
|
+
return businessRefusal(50000, "报表不存在");
|
|
95
|
+
// Live fidelity: a missing parentId answers 50000 服务异常 (the platform
|
|
96
|
+
// dereferences it), even though report/get never returns it directly.
|
|
97
|
+
if (body.parentId === undefined || body.parentId === null || body.parentId === "")
|
|
98
|
+
return businessRefusal(50000, "服务异常");
|
|
99
|
+
if (typeof body.name === "string")
|
|
100
|
+
page.name = body.name;
|
|
101
|
+
if (typeof body.icon === "string")
|
|
102
|
+
page.icon = body.icon;
|
|
103
|
+
if (typeof body.name_i18n === "string")
|
|
104
|
+
page.name_i18n = body.name_i18n;
|
|
105
|
+
if (typeof body.pcAble === "boolean")
|
|
106
|
+
page.pcAble = body.pcAble;
|
|
107
|
+
if (typeof body.mobileAble === "boolean")
|
|
108
|
+
page.mobileAble = body.mobileAble;
|
|
109
|
+
if (typeof body.parentId === "string")
|
|
110
|
+
page.parentId = body.parentId;
|
|
111
|
+
return page;
|
|
112
|
+
}
|
|
113
|
+
case "/api/api/report/logical_delete": {
|
|
114
|
+
const page = ctx.state.reportPages.get(q.code);
|
|
115
|
+
if (page) {
|
|
116
|
+
ctx.state.reportPages.delete(q.code);
|
|
117
|
+
ctx.state.biDashboards.delete(page.id);
|
|
118
|
+
}
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
// ---- BI channel ----
|
|
122
|
+
case "/dashboard/v1/report/v2/config": {
|
|
123
|
+
const objectId = String(body.objectId ?? "");
|
|
124
|
+
const dashboard = ctx.state.biDashboards.get(objectId);
|
|
125
|
+
if (!dashboard)
|
|
126
|
+
return biError("dashboard.not.exist", "The dashboard does not exist");
|
|
127
|
+
return biData({ corpId: "a", objectId, title: dashboard.title, global: dashboard.global, attributes: dashboard.attributes, charts: dashboard.charts });
|
|
128
|
+
}
|
|
129
|
+
case "/dashboard/v1/report/v2/reportpage": {
|
|
130
|
+
if (!hasConfig(body))
|
|
131
|
+
return biNoop();
|
|
132
|
+
const report = (body.report ?? {});
|
|
133
|
+
const objectId = String(report.objectId ?? "");
|
|
134
|
+
if (!objectId)
|
|
135
|
+
return biError("dashboard.save.fail", "objectId required");
|
|
136
|
+
const existing = ctx.state.biDashboards.get(objectId);
|
|
137
|
+
const dashboard = {
|
|
138
|
+
objectId,
|
|
139
|
+
title: String(report.title ?? existing?.title ?? ""),
|
|
140
|
+
global: typeof report.global === "string" ? report.global : JSON.stringify(report.global ?? {}),
|
|
141
|
+
attributes: typeof report.attributes === "string" ? report.attributes : JSON.stringify(report.attributes ?? {}),
|
|
142
|
+
charts: existing?.charts ?? [],
|
|
143
|
+
};
|
|
144
|
+
ctx.state.biDashboards.set(objectId, dashboard);
|
|
145
|
+
return biData(objectId);
|
|
146
|
+
}
|
|
147
|
+
case "/dashboard/v1/report/removeReport": {
|
|
148
|
+
if (!hasConfig(body))
|
|
149
|
+
return biNoop();
|
|
150
|
+
const objectId = String(body.objectId ?? "");
|
|
151
|
+
if (!ctx.state.biDashboards.has(objectId))
|
|
152
|
+
return biError("dashboard.not.exist", "The dashboard does not exist");
|
|
153
|
+
ctx.state.biDashboards.delete(objectId);
|
|
154
|
+
return biData(true);
|
|
155
|
+
}
|
|
156
|
+
case "/dashboard/v1/report/saveGlobal": {
|
|
157
|
+
if (!hasConfig(body))
|
|
158
|
+
return biNoop();
|
|
159
|
+
const dashboard = ctx.state.biDashboards.get(String(body.objectId ?? ""));
|
|
160
|
+
if (!dashboard)
|
|
161
|
+
return biError("dashboard.not.exist", "The dashboard does not exist");
|
|
162
|
+
dashboard.global = typeof body.global === "string" ? body.global : JSON.stringify(body.global ?? {});
|
|
163
|
+
return biData(true);
|
|
164
|
+
}
|
|
165
|
+
case "/dashboard/v1/report/saveAttributes": {
|
|
166
|
+
if (!hasConfig(body))
|
|
167
|
+
return biNoop();
|
|
168
|
+
const dashboard = ctx.state.biDashboards.get(String(body.objectId ?? ""));
|
|
169
|
+
if (!dashboard)
|
|
170
|
+
return biError("dashboard.not.exist", "The dashboard does not exist");
|
|
171
|
+
dashboard.attributes = typeof body.attributes === "string" ? body.attributes : JSON.stringify(body.attributes ?? {});
|
|
172
|
+
return biData(true);
|
|
173
|
+
}
|
|
174
|
+
case "/dashboard/v1/chart/addChart": {
|
|
175
|
+
if (!hasConfig(body))
|
|
176
|
+
return biNoop();
|
|
177
|
+
const charts = Array.isArray(body.charts) ? body.charts : [];
|
|
178
|
+
const objectId = String(charts[0]?.objectId ?? "");
|
|
179
|
+
const dashboard = ctx.state.biDashboards.get(objectId);
|
|
180
|
+
if (!dashboard)
|
|
181
|
+
return biError("dashboard.not.exist", "The dashboard does not exist");
|
|
182
|
+
for (const chart of charts) {
|
|
183
|
+
if (typeof chart.uuid !== "string" || !chart.uuid)
|
|
184
|
+
return biError("chart.invalid", "chart uuid required");
|
|
185
|
+
if (dashboard.charts.some((entry) => entry.uuid === chart.uuid))
|
|
186
|
+
return biError("chart.exist", "chart already exists");
|
|
187
|
+
dashboard.charts.push(chart);
|
|
188
|
+
}
|
|
189
|
+
return biData(true);
|
|
190
|
+
}
|
|
191
|
+
case "/dashboard/v1/chart/updateChart": {
|
|
192
|
+
if (!hasConfig(body))
|
|
193
|
+
return biNoop();
|
|
194
|
+
const charts = Array.isArray(body.charts) ? body.charts : [];
|
|
195
|
+
const objectId = String(charts[0]?.objectId ?? "");
|
|
196
|
+
const dashboard = ctx.state.biDashboards.get(objectId);
|
|
197
|
+
if (!dashboard)
|
|
198
|
+
return biError("dashboard.not.exist", "The dashboard does not exist");
|
|
199
|
+
for (const chart of charts) {
|
|
200
|
+
const index = dashboard.charts.findIndex((entry) => entry.uuid === chart.uuid);
|
|
201
|
+
if (index < 0)
|
|
202
|
+
return biError("chart.not.exist", "chart does not exist");
|
|
203
|
+
dashboard.charts[index] = chart;
|
|
204
|
+
}
|
|
205
|
+
return biData(true);
|
|
206
|
+
}
|
|
207
|
+
case "/dashboard/v1/chart/removeChart": {
|
|
208
|
+
if (!hasConfig(body))
|
|
209
|
+
return biNoop();
|
|
210
|
+
const objectId = String(body.objectId ?? "");
|
|
211
|
+
for (const dashboard of ctx.state.biDashboards.values())
|
|
212
|
+
dashboard.charts = dashboard.charts.filter((chart) => chart.uuid !== objectId);
|
|
213
|
+
return biData(true);
|
|
214
|
+
}
|
|
215
|
+
case "/dashboard/v1/chart/removeCharts": {
|
|
216
|
+
if (!hasConfig(body))
|
|
217
|
+
return biNoop();
|
|
218
|
+
const ids = new Set(Array.isArray(body.objectIds) ? body.objectIds.map(String) : []);
|
|
219
|
+
for (const dashboard of ctx.state.biDashboards.values())
|
|
220
|
+
dashboard.charts = dashboard.charts.filter((chart) => !ids.has(String(chart.uuid)));
|
|
221
|
+
return biData(true);
|
|
222
|
+
}
|
|
223
|
+
case "/dashboard/v1/report/v3/datasourcelist":
|
|
224
|
+
return biData([
|
|
225
|
+
{ dataSourceId: "model-1", displayName: "人员信息", nodeType: 0, useType: 1, objectId: "model-1", corpId: "a" },
|
|
226
|
+
]);
|
|
227
|
+
case "/dashboard/datasource/advanced_list":
|
|
228
|
+
return biData([
|
|
229
|
+
{ dataSourceId: "sql-1", displayName: "自定义查询", nodeType: 100, useType: 100, objectId: "sql-1", corpId: "a", status: 0, sort: 0, dwTableSyncFlag: false },
|
|
230
|
+
]);
|
|
231
|
+
case "/dashboard/datasource/v2/datasource_list":
|
|
232
|
+
return biData([]);
|
|
233
|
+
case "/dashboard/v1/report/v3/datasource": {
|
|
234
|
+
if (!hasConfig(body))
|
|
235
|
+
return biNoop();
|
|
236
|
+
const infos = Array.isArray(body.dataSourceInfos) ? body.dataSourceInfos : [];
|
|
237
|
+
return biData(infos.map((info) => ({ nodeType: 1, displayName: String(info.dataSourceId), dataSourceId: info.dataSourceId, schema: { dataSourceId: info.dataSourceId, tableName: `t_${String(info.dataSourceId)}` } })));
|
|
238
|
+
}
|
|
239
|
+
case "/dashboard/v1/datalogic/v3/chartdata": {
|
|
240
|
+
// Live fidelity: the endpoint wants the flattened chart with an Integer
|
|
241
|
+
// (or null) `limit`; a raw stored chart (limit is an object) answers
|
|
242
|
+
// server.error. This locks the normalization in report.ts.
|
|
243
|
+
const chart = (body.chart ?? {});
|
|
244
|
+
if (chart.limit !== null && chart.limit !== undefined && typeof chart.limit === "object")
|
|
245
|
+
return biError("server.error", "A server error, please try again later");
|
|
246
|
+
const metric = Array.isArray(chart.metric) ? chart.metric : [];
|
|
247
|
+
return biData({ series: [], total: 0, metricFields: metric.map((entry) => entry.field) });
|
|
248
|
+
}
|
|
249
|
+
default:
|
|
250
|
+
return NOT_HANDLED;
|
|
251
|
+
}
|
|
252
|
+
};
|
package/dist/routes.d.ts
ADDED
package/dist/routes.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { appRoute } from "./app.js";
|
|
2
|
+
import { b2Route } from "./b2-registration.js";
|
|
3
|
+
import { businessRuleRoute } from "./businessrule.js";
|
|
4
|
+
import { dataRuleRoute } from "./datarule.js";
|
|
5
|
+
import { dictionaryRoute } from "./dictionary.js";
|
|
6
|
+
import { environmentRoute } from "./environment.js";
|
|
7
|
+
import { fieldRoute } from "./field.js";
|
|
8
|
+
import { formRoute } from "./form.js";
|
|
9
|
+
import { listViewRoute } from "./list-view.js";
|
|
10
|
+
import { modelRoute } from "./model.js";
|
|
11
|
+
import { onlineJsRoute } from "./online-js.js";
|
|
12
|
+
import { reportRoute } from "./report.js";
|
|
13
|
+
import { ruleLifecycleRoute } from "./rule-lifecycle.js";
|
|
14
|
+
import { runtimeDataRoute } from "./runtime-data.js";
|
|
15
|
+
import { NOT_HANDLED } from "./state.js";
|
|
16
|
+
import { workflowRoute } from "./workflow.js";
|
|
17
|
+
/**
|
|
18
|
+
* Composition root for the fake wire surface: one route module per lane,
|
|
19
|
+
* mirroring src/tools.ts. Every lane is tried in turn; the first that does
|
|
20
|
+
* not answer NOT_HANDLED owns the path.
|
|
21
|
+
*/
|
|
22
|
+
const LANE_ROUTES = [
|
|
23
|
+
environmentRoute,
|
|
24
|
+
appRoute,
|
|
25
|
+
dictionaryRoute,
|
|
26
|
+
modelRoute,
|
|
27
|
+
fieldRoute,
|
|
28
|
+
dataRuleRoute,
|
|
29
|
+
formRoute,
|
|
30
|
+
businessRuleRoute,
|
|
31
|
+
ruleLifecycleRoute,
|
|
32
|
+
runtimeDataRoute,
|
|
33
|
+
workflowRoute,
|
|
34
|
+
onlineJsRoute,
|
|
35
|
+
b2Route,
|
|
36
|
+
listViewRoute,
|
|
37
|
+
reportRoute,
|
|
38
|
+
];
|
|
39
|
+
export function dispatchFakeRoute(ctx, input) {
|
|
40
|
+
for (const route of LANE_ROUTES) {
|
|
41
|
+
const result = route(ctx, input);
|
|
42
|
+
if (result !== NOT_HANDLED)
|
|
43
|
+
return result;
|
|
44
|
+
}
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type LaneRoute } from "./state.js";
|
|
2
|
+
/**
|
|
3
|
+
* S25-rule-lifecycle lane: enable/disable/delete mutations. Twin of
|
|
4
|
+
* src/lanes/rule-lifecycle.ts. The platform quirk stands: `enabled` is the
|
|
5
|
+
* truth; `status` may still read DISABLED.
|
|
6
|
+
*/
|
|
7
|
+
export declare const ruleLifecycleRoute: LaneRoute;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { NOT_HANDLED } from "./state.js";
|
|
2
|
+
/**
|
|
3
|
+
* S25-rule-lifecycle lane: enable/disable/delete mutations. Twin of
|
|
4
|
+
* src/lanes/rule-lifecycle.ts. The platform quirk stands: `enabled` is the
|
|
5
|
+
* truth; `status` may still read DISABLED.
|
|
6
|
+
*/
|
|
7
|
+
export const ruleLifecycleRoute = (ctx, input) => {
|
|
8
|
+
const q = input.query ?? {};
|
|
9
|
+
const body = (input.body ?? {});
|
|
10
|
+
switch (input.path) {
|
|
11
|
+
case "/api/api/app/businessrule/publish": {
|
|
12
|
+
const targetId = q.id ?? body.id;
|
|
13
|
+
for (const rule of ctx.state.rules.values())
|
|
14
|
+
if (rule.id === targetId)
|
|
15
|
+
rule.enabled = true;
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
case "/api/api/app/businessrule/enable": {
|
|
19
|
+
// BusinessRuleKeyRequest {schemaCode, ruleCode} flips the DRAFT row's
|
|
20
|
+
// enable switch — the face the runtime dispatcher reads
|
|
21
|
+
// (getExecutableBySchemaCodeAndCode). The platform quirk stands:
|
|
22
|
+
// enabled is the truth; status may still read DISABLED.
|
|
23
|
+
const target = [...ctx.state.rules.values()].find((rule) => rule.schemaCode === body.schemaCode && rule.code === body.ruleCode);
|
|
24
|
+
if (target)
|
|
25
|
+
target.enabled = true;
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
case "/api/api/app/businessrule/delete":
|
|
29
|
+
for (const [code, rule] of ctx.state.rules)
|
|
30
|
+
if (rule.id === q.id)
|
|
31
|
+
ctx.state.rules.delete(code);
|
|
32
|
+
return null;
|
|
33
|
+
default:
|
|
34
|
+
return NOT_HANDLED;
|
|
35
|
+
}
|
|
36
|
+
};
|