@mldong/jeeflow 1.8.15 → 1.8.17

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 CHANGED
@@ -49,6 +49,7 @@ const repo = new JdbcRepository(new MysqlAdapter(pool), new TsIDGenerator())
49
49
 
50
50
  - MySQL 连接池必须带 `supportBigNumbers: true, bigNumberStrings: true`;PostgreSQL 的 int8 默认即字符串,无此要求
51
51
  - 引擎侧已做驱动兜底:`rowId()` 把驱动返回的 number/string 统一归一化为 string,未开 `bigNumberStrings` 时小 id(Node 自建)仍可用
52
+ - `MysqlAdapter` 走 `query()` 不走 `execute()`:mysql2 预处理绑 `LIMIT ?` 会失败,分页整段 99999999(issues/66)
52
53
 
53
54
  ## 运行演示
54
55
 
package/dist/facade.js CHANGED
@@ -288,8 +288,10 @@ export class JeeflowFacade {
288
288
  }
289
289
  // ── 流程设计(需扩展仓储) ───────────────────────────────────────────────
290
290
  async designPage(args) {
291
- const [rows, total] = await this.ext().pageDesigns(toInt(args.pageNum ?? 1), toInt(args.pageSize ?? 10), undefined, parseMQuery(args));
292
- return { rows, recordCount: total };
291
+ const pageNum = toInt(args.pageNum ?? 1);
292
+ const pageSize = toInt(args.pageSize ?? 10);
293
+ const [rows, total] = await this.ext().pageDesigns(pageNum, pageSize, undefined, parseMQuery(args));
294
+ return pageData(pageNum, pageSize, total, rows.map(r => designRowToMap(r)));
293
295
  }
294
296
  /** 修改流程设计基本信息(对齐 boot3 ProcessDesignController.update,不写设计稿快照) */
295
297
  async designUpdate(args) {
@@ -571,8 +573,10 @@ export class JeeflowFacade {
571
573
  // ── 委托代理(需扩展仓储) ───────────────────────────────────────────────
572
574
  async surrogatePage(args) {
573
575
  const filters = args.operator != null ? { operator: String(args.operator) } : undefined;
574
- const [rows, total] = await this.ext().pageSurrogates(toInt(args.pageNum ?? 1), toInt(args.pageSize ?? 10), filters, parseMQuery(args));
575
- return { rows, recordCount: total };
576
+ const pageNum = toInt(args.pageNum ?? 1);
577
+ const pageSize = toInt(args.pageSize ?? 10);
578
+ const [rows, total] = await this.ext().pageSurrogates(pageNum, pageSize, filters, parseMQuery(args));
579
+ return pageData(pageNum, pageSize, total, rows);
576
580
  }
577
581
  async surrogateSave(args) {
578
582
  const ext = this.ext();
@@ -792,7 +796,7 @@ export class JeeflowFacade {
792
796
  const pageSize = toInt(args.pageSize ?? 10);
793
797
  const actorId = String(args.operator ?? 'user1');
794
798
  const { rows, total } = await this.repo.pageCcInstances(pageNum, pageSize, actorId, parseMQuery(args));
795
- return { rows: rows.map(r => ccRowToMap(r)), recordCount: total };
799
+ return pageData(pageNum, pageSize, total, rows.map(r => ccRowToMap(r)));
796
800
  }
797
801
  async taskDetail(args) {
798
802
  const taskId = toId(args.id);
@@ -819,7 +823,12 @@ export class JeeflowFacade {
819
823
  const flow = JSON.parse(toStr(def.content));
820
824
  for (const n of flow.nodes ?? []) {
821
825
  if (n.id === task.taskName) {
822
- vo.taskModel = { name: n.id, displayName: n.text?.value ?? '', type: n.type };
826
+ // issues/62:taskModel form/ext(节点字段权限,对齐 boot2)
827
+ vo.taskModel = {
828
+ name: n.id, displayName: n.text?.value ?? '', type: n.type,
829
+ form: n.properties?.form ?? null,
830
+ ext: n.properties?.field ?? null,
831
+ };
823
832
  break;
824
833
  }
825
834
  }
@@ -845,6 +854,8 @@ export class JeeflowFacade {
845
854
  return rows;
846
855
  }
847
856
  async candidatePage(args) {
857
+ const pageNum = toInt(args.pageNum ?? 1);
858
+ const pageSize = toInt(args.pageSize ?? 10);
848
859
  const taskId = toId(args.processTaskId ?? args.id);
849
860
  const task = await this.repo.findTaskById(taskId);
850
861
  if (!task)
@@ -864,13 +875,13 @@ export class JeeflowFacade {
864
875
  }
865
876
  if (candidates.length > 0) {
866
877
  const rows = candidates.map(c => ({ userId: c, realName: c }));
867
- return { rows, recordCount: rows.length };
878
+ return pageData(pageNum, pageSize, rows.length, rows);
868
879
  }
869
880
  // 无模型候选 → 用户分页搜索(依赖 userSearch 钩子)
870
881
  if (!this.userSearch)
871
882
  throw new Error('未配置 userSearch(用户搜索钩子)');
872
883
  const [rows, total] = await this.userSearch(args);
873
- return { rows, recordCount: total };
884
+ return pageData(pageNum, pageSize, total, rows);
874
885
  }
875
886
  async nextTaskCandidates(flow, taskName) {
876
887
  const result = [];
@@ -946,7 +957,7 @@ export class JeeflowFacade {
946
957
  const pageNum = toInt(args.pageNum ?? 1);
947
958
  const pageSize = toInt(args.pageSize ?? 10);
948
959
  const { rows, total } = await this.repo.pageDefines(pageNum, pageSize, parseMQuery(args));
949
- return { rows: rows.map(r => defineRowToMap(r)), recordCount: total };
960
+ return pageData(pageNum, pageSize, total, rows.map(r => defineRowToMap(r)));
950
961
  }
951
962
  async defineDetail(args) {
952
963
  const id = toId(args.id);
@@ -964,7 +975,7 @@ export class JeeflowFacade {
964
975
  const pageSize = toInt(args.pageSize ?? 10);
965
976
  const operator = String(args.operator ?? 'user1');
966
977
  const { rows, total } = await this.repo.pageInstances(pageNum, pageSize, operator, parseMQuery(args));
967
- return { rows: rows.map(r => instanceRowToMap(r)), recordCount: total };
978
+ return pageData(pageNum, pageSize, total, rows.map(r => instanceRowToMap(r)));
968
979
  }
969
980
  async instanceDetail(args) {
970
981
  const id = toId(args.id);
@@ -1029,14 +1040,14 @@ export class JeeflowFacade {
1029
1040
  const pageSize = toInt(args.pageSize ?? 10);
1030
1041
  const actorId = String(args.operator ?? 'user1');
1031
1042
  const { rows, total } = await this.repo.pageTodoTasks(pageNum, pageSize, actorId, parseMQuery(args));
1032
- return { rows: rows.map(r => taskRowToMap(r)), recordCount: total };
1043
+ return pageData(pageNum, pageSize, total, rows.map(r => taskRowToMap(r)));
1033
1044
  }
1034
1045
  async doneList(args) {
1035
1046
  const pageNum = toInt(args.pageNum ?? 1);
1036
1047
  const pageSize = toInt(args.pageSize ?? 10);
1037
1048
  const operator = String(args.operator ?? 'user1');
1038
1049
  const { rows, total } = await this.repo.pageDoneTasks(pageNum, pageSize, operator, parseMQuery(args));
1039
- return { rows: rows.map(r => taskRowToMap(r)), recordCount: total };
1050
+ return pageData(pageNum, pageSize, total, rows.map(r => taskRowToMap(r)));
1040
1051
  }
1041
1052
  /** 定义 content 解析为 LogicFlow JSON(issues/05 jsonObject) */
1042
1053
  parseGraph(content) {
@@ -1090,6 +1101,15 @@ function defineRowToMap(r) {
1090
1101
  updateTime: fmtTime(r.updateTime), updateUser: r.updateUser,
1091
1102
  };
1092
1103
  }
1104
+ /** 设计行:时间格式化(issues/63) */
1105
+ function designRowToMap(r) {
1106
+ return {
1107
+ id: r.id, name: r.name, displayName: r.displayName,
1108
+ type: r.type, icon: r.icon, isDeployed: r.isDeployed, remark: r.remark,
1109
+ createTime: fmtTime(r.createTime), createUser: r.createUser,
1110
+ updateTime: fmtTime(r.updateTime), updateUser: r.updateUser,
1111
+ };
1112
+ }
1093
1113
  /** 实例行:ext(实例变量对象)+ displayName/version(定义) */
1094
1114
  function instanceRowToMap(r) {
1095
1115
  return {
@@ -1197,3 +1217,12 @@ function toInt(v) {
1197
1217
  throw new Error('数值缺失或非法');
1198
1218
  return n;
1199
1219
  }
1220
+ /** issues/64:对齐 mldong 分页五键(Java pageResult / Go pageData) */
1221
+ function pageData(pageNum, pageSize, total, rows) {
1222
+ const pn = pageNum || 1;
1223
+ const ps = pageSize || 10;
1224
+ let totalPage = 0;
1225
+ if (total > 0 && ps > 0)
1226
+ totalPage = Math.ceil(total / ps);
1227
+ return { pageNum: pn, pageSize: ps, recordCount: total, totalPage, rows };
1228
+ }
@@ -1,18 +1,22 @@
1
1
  // MySQL 适配器(mysql2)——连接池 + `?` 占位符(与核心一致,无需转换)。
2
+ //
3
+ // 必须用 query() 而不是 execute():mysql2 execute 走预处理协议,
4
+ // LIMIT ? / OFFSET ? 会失败(Incorrect arguments / LIMIT 被绑成字符串),
5
+ // 分页接口整段变成 facade 99999999(issues/66)。Postgres 适配器本来就走 query()。
2
6
  export class MysqlConnection {
3
7
  raw;
4
8
  constructor(raw) {
5
9
  this.raw = raw;
6
10
  }
7
11
  async execute(sql, args) {
8
- await this.raw.execute(sql, args);
12
+ await this.raw.query(sql, args);
9
13
  }
10
14
  async fetchOne(sql, args) {
11
- const [rows] = await this.raw.execute(sql, args);
15
+ const [rows] = await this.raw.query(sql, args);
12
16
  return rows[0] ?? null;
13
17
  }
14
18
  async fetchAll(sql, args) {
15
- const [rows] = await this.raw.execute(sql, args);
19
+ const [rows] = await this.raw.query(sql, args);
16
20
  return rows;
17
21
  }
18
22
  async begin() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mldong/jeeflow",
3
- "version": "1.8.15",
3
+ "version": "1.8.17",
4
4
  "description": "jeeflow workflow engine — Node.js / TypeScript implementation",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -19,6 +19,7 @@
19
19
  "scripts": {
20
20
  "build": "tsc",
21
21
  "test": "node --import tsx __tests__/spec.test.ts",
22
+ "test-mysql": "node --import tsx --test __tests__/jdbc.test.ts",
22
23
  "demo": "node --import tsx demo/main.ts",
23
24
  "prepublishOnly": "npm run build"
24
25
  },