@yss123/cage-approval 0.3.0 → 0.3.1
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 +13 -0
- package/dist/bridge.js +8 -4
- package/dist/bridge.js.map +1 -1
- package/dist/deadlines.d.ts +29 -0
- package/dist/deadlines.js +72 -0
- package/dist/deadlines.js.map +1 -0
- package/dist/engine.d.ts +86 -10
- package/dist/engine.js +205 -116
- package/dist/engine.js.map +1 -1
- package/dist/execution.d.ts +41 -0
- package/dist/execution.js +85 -0
- package/dist/execution.js.map +1 -0
- package/dist/http.d.ts +2 -1
- package/dist/http.js +73 -12
- package/dist/http.js.map +1 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/openapi.d.ts +17 -0
- package/dist/openapi.js +71 -0
- package/dist/openapi.js.map +1 -0
- package/dist/operations-schema.d.ts +20 -0
- package/dist/operations-schema.js +20 -0
- package/dist/operations-schema.js.map +1 -0
- package/dist/operations.d.ts +118 -0
- package/dist/operations.js +349 -0
- package/dist/operations.js.map +1 -0
- package/dist/route.d.ts +59 -7
- package/dist/route.js +65 -27
- package/dist/route.js.map +1 -1
- package/dist/selectors.d.ts +8 -0
- package/dist/selectors.js +53 -0
- package/dist/selectors.js.map +1 -0
- package/dist/task-actions.d.ts +94 -0
- package/dist/task-actions.js +198 -0
- package/dist/task-actions.js.map +1 -0
- package/dist/task-stages.d.ts +17 -0
- package/dist/task-stages.js +47 -0
- package/dist/task-stages.js.map +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 结构化审批执行计划:把顺序、条件和 AND 并行声明编译成有界无环依赖,供原生引擎调度。
|
|
3
|
+
* 计划随既有 steps JSON 一起持久保存;节点记录的唯一键和实例行锁负责执行幂等,不创建第二套连接或任务系统。
|
|
4
|
+
* 条件只在启动时求值,旧快照没有 execution 时保持相邻顺序;本模块不支持循环、任意跳转或在途迁移。
|
|
5
|
+
*/
|
|
6
|
+
import { declError } from '@yss123/cage-kernel';
|
|
7
|
+
import { evalCondition } from './route.js';
|
|
8
|
+
/**
|
|
9
|
+
* 遍历声明并检查结构预算,返回所有叶子步骤及条件字段;用于构建期校验,不能按本次变量跳过非法配置。
|
|
10
|
+
* 最多 128 个叶子、512 个声明节点、8 层容器,每组 2–16 个具名分支;预算同时限制循环对象和恶意深嵌套。
|
|
11
|
+
*/
|
|
12
|
+
export function inspectRoute(nodes) {
|
|
13
|
+
const steps = [], fields = new Set();
|
|
14
|
+
let count = 0;
|
|
15
|
+
const visit = (items, depth) => {
|
|
16
|
+
if (depth > 8 || !Array.isArray(items) || !items.length)
|
|
17
|
+
throw declError('CAGE-APPR-006', '审批容器不能为空,嵌套最多8层');
|
|
18
|
+
for (const item of items) {
|
|
19
|
+
if (++count > 512)
|
|
20
|
+
throw declError('CAGE-APPR-006', '审批声明最多512个结构节点');
|
|
21
|
+
if (item.kind === 'when') {
|
|
22
|
+
fields.add(item.cond.field);
|
|
23
|
+
visit(item.steps, depth + 1);
|
|
24
|
+
}
|
|
25
|
+
else if (item.kind === 'parallel') {
|
|
26
|
+
if (!item.title?.trim() || item.branches.length < 2 || item.branches.length > 16 ||
|
|
27
|
+
new Set(item.branches.map(branch => branch.title)).size !== item.branches.length)
|
|
28
|
+
throw declError('CAGE-APPR-006', '并行组需标题及2–16个名称不重复的分支');
|
|
29
|
+
for (const branch of item.branches) {
|
|
30
|
+
if (branch.kind !== 'branch' || !branch.title?.trim())
|
|
31
|
+
throw declError('CAGE-APPR-006', '并行分支必须有标题');
|
|
32
|
+
visit(branch.nodes, depth + 1);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
else if (item.kind === 'step' || item.kind === 'ai') {
|
|
36
|
+
steps.push(item);
|
|
37
|
+
if (steps.length > 128)
|
|
38
|
+
throw declError('CAGE-APPR-006', '审批路由最多128个办理节点');
|
|
39
|
+
}
|
|
40
|
+
else
|
|
41
|
+
throw declError('CAGE-APPR-006', '审批包含未知节点类型');
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
visit(nodes, 0);
|
|
45
|
+
return { steps, fields: [...fields] };
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* 将结构化声明编译为拓扑有序的节点快照;每条分支继承入口依赖,后续节点等待所有分支末端。
|
|
49
|
+
* 条件为空的分支直接贡献入口依赖,因此不会产生永久等不到的汇合;整个路由为空时明确拒绝启动。
|
|
50
|
+
* 不修改声明、不访问数据库;调用方将返回结果与实例同事务保存。
|
|
51
|
+
*/
|
|
52
|
+
export function compileSteps(nodes, vars, definitionVersion) {
|
|
53
|
+
const out = [];
|
|
54
|
+
const sequence = (items, predecessors, branchPath) => {
|
|
55
|
+
let tail = predecessors;
|
|
56
|
+
for (const node of items) {
|
|
57
|
+
if (node.kind === 'when') {
|
|
58
|
+
if (evalCondition(node.cond, vars))
|
|
59
|
+
tail = sequence(node.steps, tail, branchPath);
|
|
60
|
+
}
|
|
61
|
+
else if (node.kind === 'parallel') {
|
|
62
|
+
// 各分支从同一前驱集合出发,不能让前一个分支的末端成为后一个分支的入口。
|
|
63
|
+
const incoming = tail;
|
|
64
|
+
tail = [...new Set(node.branches.flatMap(branch => sequence(branch.nodes, incoming, [...branchPath, { parallel: node.title, branch: branch.title }])))];
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
const index = out.length;
|
|
68
|
+
out.push({ ...node, execution: { schema: 1, dependsOn: [...tail], branchPath: [...branchPath], definitionVersion } });
|
|
69
|
+
tail = [index];
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return tail;
|
|
73
|
+
};
|
|
74
|
+
sequence(nodes, [], []);
|
|
75
|
+
if (!out.length)
|
|
76
|
+
throw declError('CAGE-APPR-006', '审批条件未展开出任何办理节点');
|
|
77
|
+
return out;
|
|
78
|
+
}
|
|
79
|
+
/** 解析当前实例节点的前驱;无新元数据的历史顺序实例仍只等待前一个步骤,不根据当前代码重算。 */
|
|
80
|
+
export function dependencies(steps, index) {
|
|
81
|
+
return steps[index].execution?.dependsOn ?? (index === 0 ? [] : [index - 1]);
|
|
82
|
+
}
|
|
83
|
+
/** 活跃状态包含 AI 排队/运行/人工接管和可诊断失败;只有 approved 能满足后继依赖。 */
|
|
84
|
+
export const ACTIVE_STEP_STATUSES = ['queued', 'running', 'waiting_manual', 'failed'];
|
|
85
|
+
//# sourceMappingURL=execution.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execution.js","sourceRoot":"","sources":["../src/execution.ts"],"names":[],"mappings":"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"}
|
package/dist/http.d.ts
CHANGED
|
@@ -4,7 +4,8 @@ import type { InCodeEngine } from './engine.js';
|
|
|
4
4
|
/**
|
|
5
5
|
* 在宿主 Fastify 会话/CSRF 边界内注册我的待办、对象审批历史及三种人工决定接口。
|
|
6
6
|
* 路由只接受真人用户,历史先验证对象 read;决定由目标引擎再次核对租户、待办归属、当前步骤和能力。
|
|
7
|
-
*
|
|
7
|
+
* 多个引擎的待办按时间合并,意见最多 1000 字;新操作和决定输入严格校验,不静默裁剪意见。
|
|
8
|
+
* 任务操作按租户定位引擎后交给引擎加锁/授权,历史显式指定 process 并使用游标分页。
|
|
8
9
|
*/
|
|
9
10
|
export declare function approvalRoutes(app: FastifyInstance, opts: {
|
|
10
11
|
kernel: Kernel;
|
package/dist/http.js
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
|
-
//
|
|
1
|
+
// 待办接口:本人/候选查询、领取释放、决定、转办、委派归还、前后/并行加签和操作历史;身份来自宿主会话。
|
|
2
2
|
import { cageError } from '@yss123/cage-kernel';
|
|
3
|
+
import { taskActionSchema } from './task-actions.js';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { approvalDecisionSchema } from './openapi.js';
|
|
6
|
+
import { approvalOperationsService } from './operations.js';
|
|
7
|
+
import { approvalNoticeQuerySchema, approvalUrgeSchema } from './operations-schema.js';
|
|
3
8
|
/**
|
|
4
9
|
* 在宿主 Fastify 会话/CSRF 边界内注册我的待办、对象审批历史及三种人工决定接口。
|
|
5
10
|
* 路由只接受真人用户,历史先验证对象 read;决定由目标引擎再次核对租户、待办归属、当前步骤和能力。
|
|
6
|
-
*
|
|
11
|
+
* 多个引擎的待办按时间合并,意见最多 1000 字;新操作和决定输入严格校验,不静默裁剪意见。
|
|
12
|
+
* 任务操作按租户定位引擎后交给引擎加锁/授权,历史显式指定 process 并使用游标分页。
|
|
7
13
|
*/
|
|
8
14
|
export function approvalRoutes(app, opts) {
|
|
9
15
|
const user = (req) => {
|
|
@@ -12,31 +18,86 @@ export function approvalRoutes(app, opts) {
|
|
|
12
18
|
throw cageError('UNAUTHENTICATED');
|
|
13
19
|
return ctx;
|
|
14
20
|
};
|
|
21
|
+
// 仅显式导出的运行时开放站内流程运营;未启用的旧应用仍只有原审批接口。
|
|
22
|
+
if (opts.kernel.registry.extensions.some(e => e.kind === 'RUNTIME' && e.value.name === 'approval-operations')) {
|
|
23
|
+
const operations = approvalOperationsService(opts.kernel);
|
|
24
|
+
app.get('/api/approval/notices', async (req) => {
|
|
25
|
+
const ctx = user(req), parsed = approvalNoticeQuerySchema.safeParse(req.query);
|
|
26
|
+
if (!parsed.success)
|
|
27
|
+
throw cageError('INVALID_INPUT');
|
|
28
|
+
return operations.notices(ctx, parsed.data);
|
|
29
|
+
});
|
|
30
|
+
app.get('/api/approval/requests', async (req) => operations.requests(user(req)));
|
|
31
|
+
app.post('/api/approval/notices/:id/read', async (req) => {
|
|
32
|
+
const ctx = user(req), id = req.params.id;
|
|
33
|
+
if (!z.strictObject({}).safeParse(req.body ?? {}).success)
|
|
34
|
+
throw cageError('INVALID_INPUT');
|
|
35
|
+
return operations.readNotice(id, ctx);
|
|
36
|
+
});
|
|
37
|
+
app.post('/api/approval/instances/:id/urge', async (req) => {
|
|
38
|
+
const ctx = user(req), id = req.params.id, parsed = approvalUrgeSchema.safeParse(req.body);
|
|
39
|
+
if (!z.uuid().safeParse(id).success || !parsed.success)
|
|
40
|
+
throw cageError('INVALID_INPUT');
|
|
41
|
+
return operations.urge(id, ctx, parsed.data);
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
/** 只从当前租户的已注册流程定位引擎,不以客户端传入的流程名更改待办归属。 */
|
|
45
|
+
const engineForTask = async (id, tenantId) => {
|
|
46
|
+
if (!z.uuid().safeParse(id).success)
|
|
47
|
+
throw cageError('NOT_FOUND');
|
|
48
|
+
const row = await opts.kernel.app.selectFrom('flow.approval_task as t').innerJoin('flow.approval_instance as i', 'i.id', 't.instance_id')
|
|
49
|
+
.select('i.process').where('t.id', '=', id).where('t.tenant_id', '=', tenantId).where('i.tenant_id', '=', tenantId).executeTakeFirst();
|
|
50
|
+
const engine = opts.engines.find(e => e.route.process === row?.process);
|
|
51
|
+
if (!engine)
|
|
52
|
+
throw cageError('NOT_FOUND');
|
|
53
|
+
return engine;
|
|
54
|
+
};
|
|
15
55
|
app.get('/api/approval/tasks', async (req) => {
|
|
16
56
|
const ctx = user(req);
|
|
17
57
|
const status = req.query?.status ?? 'pending';
|
|
18
58
|
const lists = await Promise.all(opts.engines.map((e) => e.tasksOf(ctx.userId, ctx.tenantId, status)));
|
|
19
59
|
return lists.flat().sort((a, b) => b.createdAt.localeCompare(a.createdAt));
|
|
20
60
|
});
|
|
61
|
+
app.get('/api/approval/candidate-tasks', async (req) => {
|
|
62
|
+
const ctx = user(req);
|
|
63
|
+
const lists = await Promise.all(opts.engines.map(engine => engine.candidateTasks(ctx.userId, ctx.tenantId)));
|
|
64
|
+
return lists.flat().sort((a, b) => b.createdAt.localeCompare(a.createdAt));
|
|
65
|
+
});
|
|
21
66
|
app.get('/api/approval/history/:aggregate/:id', async (req) => {
|
|
22
67
|
const ctx = user(req), params = req.params;
|
|
23
68
|
await opts.kernel.read.get(params.aggregate, params.id, ctx);
|
|
24
69
|
return (await Promise.all(opts.engines.map(engine => engine.history(params.aggregate, params.id, ctx)))).flat();
|
|
25
70
|
});
|
|
71
|
+
app.get('/api/approval/task-history/:process/:aggregate/:id', async (req) => {
|
|
72
|
+
const ctx = user(req), params = req.params;
|
|
73
|
+
const parsed = z.strictObject({ after: z.string().optional(), limit: z.coerce.number().int().min(1).max(200).optional() }).safeParse(req.query);
|
|
74
|
+
if (!parsed.success)
|
|
75
|
+
throw cageError('INVALID_INPUT');
|
|
76
|
+
const engine = opts.engines.find(e => e.route.process === params.process);
|
|
77
|
+
if (!engine)
|
|
78
|
+
throw cageError('NOT_FOUND');
|
|
79
|
+
return engine.taskHistory(params.aggregate, params.id, ctx, parsed.data);
|
|
80
|
+
});
|
|
81
|
+
for (const [path, action] of [['transfer', 'transfer'], ['delegate', 'delegate'], ['resolve', 'resolve'], ['add-sign', 'addSign'], ['claim', 'claim'], ['unclaim', 'unclaim']]) {
|
|
82
|
+
app.post(`/api/approval/tasks/:id/${path}`, async (req) => {
|
|
83
|
+
const ctx = user(req), id = req.params.id;
|
|
84
|
+
// action 固定来自路由;拒绝请求体伪造同名字段或非对象输入。
|
|
85
|
+
if (!req.body || typeof req.body !== 'object' || Array.isArray(req.body) || 'action' in req.body)
|
|
86
|
+
throw cageError('INVALID_INPUT');
|
|
87
|
+
const parsed = taskActionSchema.safeParse({ ...req.body, action });
|
|
88
|
+
if (!parsed.success)
|
|
89
|
+
throw cageError('INVALID_INPUT');
|
|
90
|
+
return (await engineForTask(id, ctx.tenantId)).act(id, ctx.userId, ctx.tenantId, parsed.data);
|
|
91
|
+
});
|
|
92
|
+
}
|
|
26
93
|
for (const outcome of ['approve', 'reject', 'return']) {
|
|
27
94
|
app.post(`/api/approval/tasks/:id/${outcome}`, async (req) => {
|
|
28
95
|
const ctx = user(req);
|
|
29
96
|
const id = req.params.id;
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
const owns = await opts.kernel.app.selectFrom('flow.approval_task as t').innerJoin('flow.approval_instance as i', 'i.id', 't.instance_id')
|
|
35
|
-
.select('t.id').where('t.id', '=', id).where('i.process', '=', e.route.process).executeTakeFirst();
|
|
36
|
-
if (owns)
|
|
37
|
-
return e.decide(id, ctx.userId, ctx.tenantId, outcome === 'approve' ? 'approved' : outcome === 'return' ? 'returned' : 'rejected', comment);
|
|
38
|
-
}
|
|
39
|
-
throw cageError('NOT_FOUND');
|
|
97
|
+
const parsed = approvalDecisionSchema.safeParse(req.body ?? {});
|
|
98
|
+
if (!parsed.success)
|
|
99
|
+
throw cageError('INVALID_INPUT');
|
|
100
|
+
return (await engineForTask(id, ctx.tenantId)).decide(id, ctx.userId, ctx.tenantId, outcome === 'approve' ? 'approved' : outcome === 'return' ? 'returned' : 'rejected', parsed.data.comment, parsed.data.expectedRevision);
|
|
40
101
|
});
|
|
41
102
|
}
|
|
42
103
|
}
|
package/dist/http.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAAA,sDAAsD;AACtD,OAAO,EAAE,SAAS,EAAyB,MAAM,qBAAqB,CAAC;AAGvE,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,EAAE,yBAAyB,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAEvF;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,GAAoB,EAAE,IAA2E;IAC9H,MAAM,IAAI,GAAG,CAAC,GAAQ,EAAE,EAAE;QACxB,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC5B,IAAI,CAAC,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,GAAG,CAAC,MAAM;YAAE,MAAM,SAAS,CAAC,iBAAiB,CAAC,CAAC;QAC/F,OAAO,GAAG,CAAC;IACb,CAAC,CAAC;IACF,qCAAqC;IACrC,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,CAAC,KAAK,CAAC,IAAI,KAAK,qBAAqB,CAAC,EAAE,CAAC;QAC9G,MAAM,UAAU,GAAG,yBAAyB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC1D,GAAG,CAAC,GAAG,CAAC,uBAAuB,EAAE,KAAK,EAAC,GAAG,EAAC,EAAE;YAC3C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,yBAAyB,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YAC/E,IAAI,CAAC,MAAM,CAAC,OAAO;gBAAE,MAAM,SAAS,CAAC,eAAe,CAAC,CAAC;YACtD,OAAO,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;QAC9C,CAAC,CAAC,CAAC;QACH,GAAG,CAAC,GAAG,CAAC,wBAAwB,EAAE,KAAK,EAAC,GAAG,EAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAC/E,GAAG,CAAC,IAAI,CAAC,gCAAgC,EAAE,KAAK,EAAC,GAAG,EAAC,EAAE;YACrD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,GAAI,GAAG,CAAC,MAAyB,CAAC,EAAE,CAAC;YAC9D,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,OAAO;gBAAE,MAAM,SAAS,CAAC,eAAe,CAAC,CAAC;YAC5F,OAAO,UAAU,CAAC,UAAU,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;QACxC,CAAC,CAAC,CAAC;QACH,GAAG,CAAC,IAAI,CAAC,kCAAkC,EAAE,KAAK,EAAC,GAAG,EAAC,EAAE;YACvD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,GAAI,GAAG,CAAC,MAAyB,CAAC,EAAE,EAAE,MAAM,GAAG,kBAAkB,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAC/G,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO;gBAAE,MAAM,SAAS,CAAC,eAAe,CAAC,CAAC;YACzF,OAAO,UAAU,CAAC,IAAI,CAAC,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;QAC/C,CAAC,CAAC,CAAC;IACL,CAAC;IACD,0CAA0C;IAC1C,MAAM,aAAa,GAAG,KAAK,EAAE,EAAU,EAAE,QAAgB,EAAE,EAAE;QAC3D,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,OAAO;YAAE,MAAM,SAAS,CAAC,WAAW,CAAC,CAAC;QAClE,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,yBAAyB,CAAC,CAAC,SAAS,CAAC,6BAA6B,EAAE,MAAM,EAAE,eAAe,CAAC;aACtI,MAAM,CAAC,WAAW,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,aAAa,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC,KAAK,CAAC,aAAa,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC,gBAAgB,EAAE,CAAC;QACzI,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,KAAK,GAAG,EAAE,OAAO,CAAC,CAAC;QACxE,IAAI,CAAC,MAAM;YAAE,MAAM,SAAS,CAAC,WAAW,CAAC,CAAC;QAC1C,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC;IACF,GAAG,CAAC,GAAG,CAAC,qBAAqB,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;QAC3C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;QACtB,MAAM,MAAM,GAAI,GAAG,CAAC,KAAa,EAAE,MAAM,IAAI,SAAS,CAAC;QACvD,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,MAAO,EAAE,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;QACvG,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;IAC7E,CAAC,CAAC,CAAC;IACH,GAAG,CAAC,GAAG,CAAC,+BAA+B,EAAE,KAAK,EAAC,GAAG,EAAC,EAAE;QACnD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;QACtB,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,cAAc,CAAC,GAAG,CAAC,MAAO,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QAC9G,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;IAC7E,CAAC,CAAC,CAAC;IACH,GAAG,CAAC,GAAG,CAAC,sCAAsC,EAAE,KAAK,EAAC,GAAG,EAAC,EAAE;QAC1D,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,GAAG,CAAC,MAA2C,CAAC;QAChF,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;QAC7D,OAAO,CAAC,MAAM,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAClH,CAAC,CAAC,CAAC;IACH,GAAG,CAAC,GAAG,CAAC,oDAAoD,EAAE,KAAK,EAAC,GAAG,EAAC,EAAE;QACxE,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,GAAG,CAAC,MAA4D,CAAC;QACjG,MAAM,MAAM,GAAG,CAAC,CAAC,YAAY,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAChJ,IAAI,CAAC,MAAM,CAAC,OAAO;YAAE,MAAM,SAAS,CAAC,eAAe,CAAC,CAAC;QACtD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,KAAK,MAAM,CAAC,OAAO,CAAC,CAAC;QAC1E,IAAI,CAAC,MAAM;YAAE,MAAM,SAAS,CAAC,WAAW,CAAC,CAAC;QAC1C,OAAO,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;IAC3E,CAAC,CAAC,CAAC;IACH,KAAK,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,UAAU,CAAC,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC,EAAE,CAAC,UAAU,EAAE,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC,CAAU,EAAE,CAAC;QACxL,GAAG,CAAC,IAAI,CAAC,2BAA2B,IAAI,EAAE,EAAE,KAAK,EAAC,GAAG,EAAC,EAAE;YACtD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,GAAI,GAAG,CAAC,MAAyB,CAAC,EAAE,CAAC;YAC9D,mCAAmC;YACnC,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,QAAQ,IAAI,GAAG,CAAC,IAAI;gBAAE,MAAM,SAAS,CAAC,eAAe,CAAC,CAAC;YACnI,MAAM,MAAM,GAAG,gBAAgB,CAAC,SAAS,CAAC,EAAE,GAAG,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;YACnE,IAAI,CAAC,MAAM,CAAC,OAAO;gBAAE,MAAM,SAAS,CAAC,eAAe,CAAC,CAAC;YACtD,OAAO,CAAC,MAAM,aAAa,CAAC,EAAE,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,MAAO,EAAE,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;QACjG,CAAC,CAAC,CAAC;IACL,CAAC;IACD,KAAK,MAAM,OAAO,IAAI,CAAC,SAAS,EAAE,QAAQ,EAAE,QAAQ,CAAU,EAAE,CAAC;QAC/D,GAAG,CAAC,IAAI,CAAC,2BAA2B,OAAO,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;YAC3D,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;YACtB,MAAM,EAAE,GAAI,GAAG,CAAC,MAAc,CAAC,EAAY,CAAC;YAC5C,MAAM,MAAM,GAAG,sBAAsB,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;YAChE,IAAI,CAAC,MAAM,CAAC,OAAO;gBAAE,MAAM,SAAS,CAAC,eAAe,CAAC,CAAC;YACtD,OAAO,CAAC,MAAM,aAAa,CAAC,EAAE,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,GAAG,CAAC,MAAO,EAAE,GAAG,CAAC,QAAQ,EACjF,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAC5I,CAAC,CAAC,CAAC;IACL,CAAC;AACH,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -4,8 +4,12 @@
|
|
|
4
4
|
*/
|
|
5
5
|
export * from './types.js';
|
|
6
6
|
export { applyOutcome, bindApproval } from './bridge.js';
|
|
7
|
-
export { route, step, when, approver, gt, gte, lt, lte, eq, ne, isIn, evalCondition, resolveSteps, FLOW_DDL, type Route, type RouteNode, type Step, type When, type Approver, type Condition, } from './route.js';
|
|
7
|
+
export { route, step, when, parallel, branch, approver, gt, gte, lt, lte, eq, ne, isIn, evalCondition, resolveSteps, FLOW_DDL, type Route, type RouteNode, type Step, type When, type Parallel, type Branch, type Approver, type Condition, } from './route.js';
|
|
8
8
|
export { InCodeEngine, type TaskView } from './engine.js';
|
|
9
9
|
export { approvalRoutes } from './http.js';
|
|
10
|
+
export { approvalOpenApi } from './openapi.js';
|
|
10
11
|
export { approvalRoleContext, type AiStep, type AiStepOptions, type AiDecision } from './ai.js';
|
|
11
12
|
export type { ApprovalStep } from './route.js';
|
|
13
|
+
export { taskActionSchema, type TaskActionPolicy, type TaskActionInput, type TaskActionResult } from './task-actions.js';
|
|
14
|
+
export { approvalOperations, approvalOperationsService, ApprovalOperationsService, type ApprovalNoticeView, type ApprovalRequestView, type ApprovalNoticeOptions } from './operations.js';
|
|
15
|
+
export type { ApprovalSla, ApprovalReminderPolicy } from './deadlines.js';
|
package/dist/index.js
CHANGED
|
@@ -5,8 +5,11 @@
|
|
|
5
5
|
*/
|
|
6
6
|
export * from './types.js';
|
|
7
7
|
export { applyOutcome, bindApproval } from './bridge.js';
|
|
8
|
-
export { route, step, when, approver, gt, gte, lt, lte, eq, ne, isIn, evalCondition, resolveSteps, FLOW_DDL, } from './route.js';
|
|
8
|
+
export { route, step, when, parallel, branch, approver, gt, gte, lt, lte, eq, ne, isIn, evalCondition, resolveSteps, FLOW_DDL, } from './route.js';
|
|
9
9
|
export { InCodeEngine } from './engine.js';
|
|
10
10
|
export { approvalRoutes } from './http.js';
|
|
11
|
+
export { approvalOpenApi } from './openapi.js';
|
|
11
12
|
export { approvalRoleContext } from './ai.js';
|
|
13
|
+
export { taskActionSchema } from './task-actions.js';
|
|
14
|
+
export { approvalOperations, approvalOperationsService, ApprovalOperationsService } from './operations.js';
|
|
12
15
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAC/C;;;GAGG;AACH,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EACL,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,YAAY,EAAE,QAAQ,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAC/C;;;GAGG;AACH,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EACL,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,YAAY,EAAE,QAAQ,GAErH,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,YAAY,EAAiB,MAAM,aAAa,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,mBAAmB,EAAoD,MAAM,SAAS,CAAC;AAEhG,OAAO,EAAE,gBAAgB,EAAsE,MAAM,mBAAmB,CAAC;AACzH,OAAO,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,yBAAyB,EACA,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 审批 HTTP 的 OpenAPI 描述,由 cage-http 在已装配代码内审批引擎时合并。
|
|
3
|
+
* 输入结构从任务动作 schema 产生,描述不能代替服务端当前任务、权限和事务验证;不读取业务数据。
|
|
4
|
+
*/
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
/** HTTP 决定输入与文档共用;旧节点可不带版本,新流转节点由引擎进一步要求 expectedRevision。 */
|
|
7
|
+
export declare const approvalDecisionSchema: z.ZodObject<{
|
|
8
|
+
comment: z.ZodOptional<z.ZodString>;
|
|
9
|
+
expectedRevision: z.ZodOptional<z.ZodNumber>;
|
|
10
|
+
}, z.core.$strict>;
|
|
11
|
+
/**
|
|
12
|
+
* 生成待办、审批决定、流转动作和操作历史路径;全部复用宿主 Cookie/CSRF,不开放流程身份命令。
|
|
13
|
+
* 文档中的 200 表示本次操作提交,finished:false 不代表整个审批完成;错误保留框架协议码。
|
|
14
|
+
*/
|
|
15
|
+
export declare function approvalOpenApi(options?: {
|
|
16
|
+
operations?: boolean;
|
|
17
|
+
}): Record<string, Record<string, unknown>>;
|
package/dist/openapi.js
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 审批 HTTP 的 OpenAPI 描述,由 cage-http 在已装配代码内审批引擎时合并。
|
|
3
|
+
* 输入结构从任务动作 schema 产生,描述不能代替服务端当前任务、权限和事务验证;不读取业务数据。
|
|
4
|
+
*/
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import { taskActionSchema } from './task-actions.js';
|
|
7
|
+
import { approvalUrgeSchema } from './operations-schema.js';
|
|
8
|
+
/** HTTP 决定输入与文档共用;旧节点可不带版本,新流转节点由引擎进一步要求 expectedRevision。 */
|
|
9
|
+
export const approvalDecisionSchema = z.strictObject({
|
|
10
|
+
comment: z.string().max(1000).optional(),
|
|
11
|
+
expectedRevision: z.number().int().min(0).max(Number.MAX_SAFE_INTEGER).optional(),
|
|
12
|
+
});
|
|
13
|
+
/**
|
|
14
|
+
* 生成待办、审批决定、流转动作和操作历史路径;全部复用宿主 Cookie/CSRF,不开放流程身份命令。
|
|
15
|
+
* 文档中的 200 表示本次操作提交,finished:false 不代表整个审批完成;错误保留框架协议码。
|
|
16
|
+
*/
|
|
17
|
+
export function approvalOpenApi(options = {}) {
|
|
18
|
+
const id = { name: 'id', in: 'path', required: true, schema: { type: 'string', format: 'uuid' } };
|
|
19
|
+
const responses = { 200: { description: '本次操作成功;审批结束与否查看 finished,任务操作返回 revision/createdTaskIds' },
|
|
20
|
+
default: { description: '身份、能力、范围、任务状态、版本或领域约束拒绝', content: { 'application/json': { schema: { $ref: '#/components/schemas/CageError' } } } } };
|
|
21
|
+
const paths = {
|
|
22
|
+
'/api/approval/tasks': { get: { summary: '本人审批待办,含 revision/委派状态/节点政策', parameters: [{ name: 'status', in: 'query', schema: { type: 'string', default: 'pending' } }], responses } },
|
|
23
|
+
'/api/approval/candidate-tasks': { get: { summary: '当前有候选身份、批准权限和单据范围的未领取任务', description: '每流程从最近 200 项未领取任务中筛选;查询不占用任务,领取时再次验证。', responses } },
|
|
24
|
+
};
|
|
25
|
+
for (const action of taskActionSchema.options) {
|
|
26
|
+
const name = action.shape.action.value;
|
|
27
|
+
const path = name === 'addSign' ? 'add-sign' : name;
|
|
28
|
+
const { action: _discriminator, ...body } = action.shape;
|
|
29
|
+
paths[`/api/approval/tasks/{id}/${path}`] = { post: {
|
|
30
|
+
summary: `审批任务 ${name}`, description: '节点须显式开放;任务归属、revision 与接收人权限由服务端重新核验。需会话和 CSRF。',
|
|
31
|
+
parameters: [id], requestBody: { required: true, content: { 'application/json': { schema: z.toJSONSchema(z.strictObject(body)) } } }, responses,
|
|
32
|
+
} };
|
|
33
|
+
}
|
|
34
|
+
for (const outcome of ['approve', 'reject', 'return'])
|
|
35
|
+
paths[`/api/approval/tasks/{id}/${outcome}`] = { post: {
|
|
36
|
+
summary: `审批决定 ${outcome}`, description: '候选领取或启用任务流转的节点必须提供 expectedRevision;waiting、未领取和受托未归还不能决定,最终结论走领域命令。',
|
|
37
|
+
parameters: [id], requestBody: { content: { 'application/json': { schema: z.toJSONSchema(approvalDecisionSchema) } } }, responses,
|
|
38
|
+
} };
|
|
39
|
+
paths['/api/approval/task-history/{process}/{aggregate}/{id}'] = { get: {
|
|
40
|
+
summary: '当前可读单据的人工任务操作历史', parameters: [id,
|
|
41
|
+
...['process', 'aggregate'].map(name => ({ name, in: 'path', required: true, schema: { type: 'string' } })),
|
|
42
|
+
{ name: 'after', in: 'query', schema: { type: 'string', pattern: '^(0|[1-9][0-9]{0,18})$' } },
|
|
43
|
+
{ name: 'limit', in: 'query', schema: { type: 'integer', minimum: 1, maximum: 200, default: 50 } }],
|
|
44
|
+
description: '按递增记录 ID 分页,nextCursor 为 null 表示当前末尾;校验单据 read/范围。', responses,
|
|
45
|
+
} };
|
|
46
|
+
if (options.operations) {
|
|
47
|
+
paths['/api/approval/notices'] = { get: {
|
|
48
|
+
summary: '本人当前授权可见的临期、超时和催办站内提醒',
|
|
49
|
+
description: '返回 items 与 nextCursor;按当前单据权限及接收关系过滤,空页仍可能有下一页。自然分钟时限不替代审批决定。',
|
|
50
|
+
parameters: [
|
|
51
|
+
{ name: 'after', in: 'query', schema: { type: 'string', pattern: '^(0|[1-9][0-9]{0,18})$' } },
|
|
52
|
+
{ name: 'limit', in: 'query', schema: { type: 'integer', minimum: 1, maximum: 200, default: 50 } },
|
|
53
|
+
{ name: 'unreadOnly', in: 'query', schema: { type: 'boolean', default: false } },
|
|
54
|
+
], responses,
|
|
55
|
+
} };
|
|
56
|
+
paths['/api/approval/notices/{id}/read'] = { post: {
|
|
57
|
+
summary: '标记本人可见提醒已读', description: '重复调用保留首次已读时间;读取或接收权限失效时不可操作。需会话和 CSRF。',
|
|
58
|
+
parameters: [{ ...id, schema: { type: 'string', pattern: '^[1-9][0-9]{0,18}$' } }],
|
|
59
|
+
requestBody: { content: { 'application/json': { schema: { type: 'object', additionalProperties: false } } } }, responses,
|
|
60
|
+
} };
|
|
61
|
+
paths['/api/approval/requests'] = { get: {
|
|
62
|
+
summary: '本人发起且显式开放催办的运行实例', description: '返回 currentSteps、各分支 activeSteps、最近截止 dueAt 与 nextUrgeAt;currentStep 仅为最小活跃索引。身份来自提交时的 requesterField 快照,仍需当前单据 read/范围。', responses,
|
|
63
|
+
} };
|
|
64
|
+
paths['/api/approval/instances/{id}/urge'] = { post: {
|
|
65
|
+
summary: '申请人催办当前流程节点', description: '锁定实例复核申请人、节点和业务版本;并行实例必须提交 expectedSteps 完整活跃集合,冷却按实例持久共享。recipientCount 为任务与接收人配对数。无合格接收人明确失败,仅生成站内提醒。',
|
|
66
|
+
parameters: [id], requestBody: { required: true, content: { 'application/json': { schema: z.toJSONSchema(approvalUrgeSchema) } } }, responses,
|
|
67
|
+
} };
|
|
68
|
+
}
|
|
69
|
+
return paths;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=openapi.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openapi.js","sourceRoot":"","sources":["../src/openapi.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 通用审批运营 HTTP 的封闭输入协议,供路由校验与 OpenAPI 共用。
|
|
3
|
+
* 这里只做格式约束;本人身份、实例版本、节点状态和冷却在 operations 服务的事务内复核。
|
|
4
|
+
*/
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
/** 已读取实例当前节点与共享催办说明;不允许客户端指定收件人、申请人或冷却时间。 */
|
|
7
|
+
export declare const approvalUrgeSchema: z.ZodObject<{
|
|
8
|
+
expectedStep: z.ZodNumber;
|
|
9
|
+
expectedSteps: z.ZodOptional<z.ZodArray<z.ZodNumber>>;
|
|
10
|
+
reason: z.ZodString;
|
|
11
|
+
}, z.core.$strict>;
|
|
12
|
+
/** 提醒游标按 bigint 字符串传输;HTTP 查询布尔值显式解析,避免把字符串 false 转成 true。 */
|
|
13
|
+
export declare const approvalNoticeQuerySchema: z.ZodObject<{
|
|
14
|
+
after: z.ZodOptional<z.ZodString>;
|
|
15
|
+
limit: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
|
|
16
|
+
unreadOnly: z.ZodOptional<z.ZodPipe<z.ZodEnum<{
|
|
17
|
+
true: "true";
|
|
18
|
+
false: "false";
|
|
19
|
+
}>, z.ZodTransform<boolean, "true" | "false">>>;
|
|
20
|
+
}, z.core.$strict>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 通用审批运营 HTTP 的封闭输入协议,供路由校验与 OpenAPI 共用。
|
|
3
|
+
* 这里只做格式约束;本人身份、实例版本、节点状态和冷却在 operations 服务的事务内复核。
|
|
4
|
+
*/
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
/** 已读取实例当前节点与共享催办说明;不允许客户端指定收件人、申请人或冷却时间。 */
|
|
7
|
+
export const approvalUrgeSchema = z.strictObject({
|
|
8
|
+
expectedStep: z.number().int().min(0).max(Number.MAX_SAFE_INTEGER),
|
|
9
|
+
/** 并行实例必填,按升序携带读取到的完整活跃节点集合;顺序旧客户端可省略。 */
|
|
10
|
+
expectedSteps: z.array(z.number().int().min(0).max(Number.MAX_SAFE_INTEGER)).min(1).max(128)
|
|
11
|
+
.refine(items => items.every((item, index) => index === 0 || items[index - 1] < item)).optional(),
|
|
12
|
+
reason: z.string().trim().min(1).max(1000),
|
|
13
|
+
});
|
|
14
|
+
/** 提醒游标按 bigint 字符串传输;HTTP 查询布尔值显式解析,避免把字符串 false 转成 true。 */
|
|
15
|
+
export const approvalNoticeQuerySchema = z.strictObject({
|
|
16
|
+
after: z.string().regex(/^(0|[1-9]\d{0,18})$/).optional(),
|
|
17
|
+
limit: z.coerce.number().int().min(1).max(200).optional(),
|
|
18
|
+
unreadOnly: z.enum(['true', 'false']).transform(value => value === 'true').optional(),
|
|
19
|
+
});
|
|
20
|
+
//# sourceMappingURL=operations-schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operations-schema.js","sourceRoot":"","sources":["../src/operations-schema.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,6CAA6C;AAC7C,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,YAAY,CAAC;IAC/C,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,gBAAgB,CAAC;IAClE,0CAA0C;IAC1C,aAAa,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;SACzF,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,CAAC,IAAI,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE;IACnG,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC;CAC3C,CAAC,CAAC;AAEH,8DAA8D;AAC9D,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,CAAC,YAAY,CAAC;IACtD,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC,QAAQ,EAAE;IACzD,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE;IACzD,UAAU,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,KAAK,MAAM,CAAC,CAAC,QAAQ,EAAE;CACtF,CAAC,CAAC"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { type Ctx, type Kernel, type Registry, type RuntimeDefinition, type RuntimeService } from '@yss123/cage-kernel';
|
|
2
|
+
import { type BranchLocation } from './execution.js';
|
|
3
|
+
/** 持久站内提醒摘要;不返回路由变量、人员政策或未掩码业务字段,ID 用十进制字符串避免 bigint 精度损失。 */
|
|
4
|
+
export interface ApprovalNoticeView {
|
|
5
|
+
/** 服务端游标 ID,不能转成 JS number。 */
|
|
6
|
+
id: string;
|
|
7
|
+
/** 当前接收关系对应的任务与流程实例。 */
|
|
8
|
+
taskId: string;
|
|
9
|
+
instanceId: string;
|
|
10
|
+
/** 已注册流程、业务对象类型及对象 ID,仅当前可见单据才会返回。 */
|
|
11
|
+
process: string;
|
|
12
|
+
aggregate: string;
|
|
13
|
+
businessKey: string;
|
|
14
|
+
/** 0 基节点索引及提交时保存的节点标题。 */
|
|
15
|
+
step: number;
|
|
16
|
+
title: string;
|
|
17
|
+
/** 临期、超时或申请人催办;超时仍保持原来的审批状态。 */
|
|
18
|
+
kind: 'due_soon' | 'overdue' | 'urge';
|
|
19
|
+
/** 自动提醒为 null;人工催办记录当时申请人的用户 ID。 */
|
|
20
|
+
actorId: string | null;
|
|
21
|
+
/** 人工催办共享说明,自动提醒为 null;读取时仍校验当前接收资格。 */
|
|
22
|
+
reason: string | null;
|
|
23
|
+
/** UTC ISO 时间;readAt 为 null 表示本人尚未标记已读,dueAt 为 null 表示未声明时限。 */
|
|
24
|
+
createdAt: string;
|
|
25
|
+
readAt: string | null;
|
|
26
|
+
dueAt: string | null;
|
|
27
|
+
}
|
|
28
|
+
/** 本人发起且仍运行的可见申请;只列实例明确保存 requesterField 政策的流程,不反推旧实例申请人。 */
|
|
29
|
+
export interface ApprovalRequestView {
|
|
30
|
+
/** 实例 ID,用于催办目标,业务单据重提时新实例不会被旧页面误催办。 */
|
|
31
|
+
id: string;
|
|
32
|
+
/** 流程与单据定位;不暴露路由变量及敏感业务明文。 */
|
|
33
|
+
process: string;
|
|
34
|
+
aggregate: string;
|
|
35
|
+
businessKey: string;
|
|
36
|
+
/** 最小活跃节点索引,仅为旧客户端的兼容摘要;并行催办必须同时提交 currentSteps。 */
|
|
37
|
+
currentStep: number;
|
|
38
|
+
title: string;
|
|
39
|
+
/** 全部活跃节点的索引;并行分支任一推进后旧集合失效。 */
|
|
40
|
+
currentSteps: number[];
|
|
41
|
+
/** 各分支当前环节及独立截止时间,主线 branchPath 为空。 */
|
|
42
|
+
activeSteps: {
|
|
43
|
+
step: number;
|
|
44
|
+
title: string;
|
|
45
|
+
dueAt: string | null;
|
|
46
|
+
branchPath: BranchLocation[];
|
|
47
|
+
}[];
|
|
48
|
+
/** 节点总办理截止时间及下次可催办时间;null 分别代表无 SLA 和尚未催办。 */
|
|
49
|
+
dueAt: string | null;
|
|
50
|
+
nextUrgeAt: string | null;
|
|
51
|
+
}
|
|
52
|
+
/** 收件箱分页参数;after 是上次返回的十进制游标,过滤后本页可为空但仍返回后续游标。 */
|
|
53
|
+
export interface ApprovalNoticeOptions {
|
|
54
|
+
after?: string;
|
|
55
|
+
/** 默认 50,最多扫描 200 条本人记录;当前权限不符的记录不返回。 */
|
|
56
|
+
limit?: number;
|
|
57
|
+
/** true 仅扫描本人未读记录;省略或 false 包含已读。 */
|
|
58
|
+
unreadOnly?: boolean;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* 原生审批的可选持久运营服务,公开方法重新校验内部调用输入,不依赖 HTTP 才执行校验。
|
|
62
|
+
* 实例锁与 SQL 唯一键支持多个 worker;本对象不持有额外连接、定时器或队列,close 无需关闭宿主资源。
|
|
63
|
+
*/
|
|
64
|
+
export declare class ApprovalOperationsService implements RuntimeService {
|
|
65
|
+
private readonly k;
|
|
66
|
+
constructor(k: Kernel);
|
|
67
|
+
/** 仅扫描当前仍注册的原生流程;没有 ROUTE 的空应用启用运行时也不访问不存在的 flow 表。 */
|
|
68
|
+
private processes;
|
|
69
|
+
/** 启动时验证新迁移可读;无原生路由时服务为空操作,不代替 migrate 自动建表。 */
|
|
70
|
+
ready(): Promise<void>;
|
|
71
|
+
/** 服务不创建独立资源,停机时由宿主 worker 等待在途事务并关闭宿主连接。 */
|
|
72
|
+
close(): Promise<void>;
|
|
73
|
+
/**
|
|
74
|
+
* 每轮最多检查 25 个到期节点,实例 FOR UPDATE SKIP LOCKED 后再读节点与任务,保持既有锁序。
|
|
75
|
+
* 扫描时间持久后移一秒,已投递节点不会饿死后续节点;未找到当前合格人也保留后续补投机会。
|
|
76
|
+
* 超时优先于临期,停机跨过截止时不会同时补两阶段;新接收人下一轮补投,既有人由唯一键去重。
|
|
77
|
+
*/
|
|
78
|
+
tick(signal?: AbortSignal): Promise<number>;
|
|
79
|
+
/**
|
|
80
|
+
* 本人收件箱按 bigint 游标递增分页,返回前重新核对当前任务接收关系与业务权限。
|
|
81
|
+
* 转出、候选被他人领取、任务结束、停用或撤权后对应内容不再可见;过滤不篡改原始通知或全局已读状态。
|
|
82
|
+
*/
|
|
83
|
+
notices(ctx: Ctx, options?: ApprovalNoticeOptions): Promise<{
|
|
84
|
+
items: ApprovalNoticeView[];
|
|
85
|
+
nextCursor: string | null;
|
|
86
|
+
}>;
|
|
87
|
+
/** 本人已读是幂等操作;先锁实例再核验接收资格,不能用他人 ID 或旧转办页面修改提醒。 */
|
|
88
|
+
readNotice(id: string, ctx: Ctx): Promise<{
|
|
89
|
+
id: string;
|
|
90
|
+
readAt: string;
|
|
91
|
+
}>;
|
|
92
|
+
/** 本人当前申请清单最多返回最近 200 项;当前 read/范围和提交版本均复核,旧实例不补造催办政策。 */
|
|
93
|
+
requests(ctx: Ctx): Promise<ApprovalRequestView[]>;
|
|
94
|
+
/**
|
|
95
|
+
* 发起人催办当前实例/节点;锁内再次检查业务版本、本人字段、范围与冷却,收件人与说明不可由客户端越权指定。
|
|
96
|
+
* 一次成功催办独立来源去重,投递、不可覆盖动作历史与冷却同时提交;无可处理人工任务明确拒绝且不占冷却。
|
|
97
|
+
*/
|
|
98
|
+
urge(instanceId: string, ctx: Ctx, input: {
|
|
99
|
+
expectedStep: number;
|
|
100
|
+
expectedSteps?: number[];
|
|
101
|
+
reason: string;
|
|
102
|
+
}): Promise<{
|
|
103
|
+
recipientCount: number;
|
|
104
|
+
nextUrgeAt: string;
|
|
105
|
+
}>;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* 取得当前内核唯一运营服务;只有 domain 显式导出 approvalOperations 才开放,不因安装包而隐式启用。
|
|
109
|
+
* HTTP 和 worker 复用同一弱缓存对象,但一致性由数据库事务保证,不能依赖这个内存缓存跨进程去重。
|
|
110
|
+
*/
|
|
111
|
+
export declare function approvalOperationsService(kernel: Kernel): ApprovalOperationsService;
|
|
112
|
+
/**
|
|
113
|
+
* 独立 RUNTIME 声明启用审批运营;不能把同一对象同时标记 ROUTE,否则注册表只会识别其运行时身份。
|
|
114
|
+
* 迁移由原生路由统一追加,空应用可以启用本声明且保持无操作;不新增生产角色能力或默认授权。
|
|
115
|
+
*/
|
|
116
|
+
export declare function approvalOperations(): RuntimeDefinition & {
|
|
117
|
+
validate(registry: Registry): void;
|
|
118
|
+
};
|