@yss123/cage-kernel 0.1.0 → 0.3.0
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 +71 -9
- package/dist/authorization.d.ts +34 -0
- package/dist/authorization.js +89 -0
- package/dist/authorization.js.map +1 -0
- package/dist/brands.d.ts +10 -0
- package/dist/brands.js +11 -1
- package/dist/brands.js.map +1 -1
- package/dist/db/connect.d.ts +14 -0
- package/dist/db/connect.js +18 -2
- package/dist/db/connect.js.map +1 -1
- package/dist/db/ddl.d.ts +40 -1
- package/dist/db/ddl.js +111 -7
- package/dist/db/ddl.js.map +1 -1
- package/dist/db/event-version-schema.d.ts +9 -0
- package/dist/db/event-version-schema.js +10 -0
- package/dist/db/event-version-schema.js.map +1 -0
- package/dist/db/index.d.ts +4 -0
- package/dist/db/index.js +4 -0
- package/dist/db/index.js.map +1 -1
- package/dist/db/migrate.d.ts +10 -0
- package/dist/db/migrate.js +9 -1
- package/dist/db/migrate.js.map +1 -1
- package/dist/db/rows.d.ts +2 -0
- package/dist/db/rows.js +6 -0
- package/dist/db/rows.js.map +1 -1
- package/dist/db/runtime-schema.d.ts +9 -0
- package/dist/db/runtime-schema.js +41 -0
- package/dist/db/runtime-schema.js.map +1 -0
- package/dist/db/session.d.ts +6 -0
- package/dist/db/session.js +6 -0
- package/dist/db/session.js.map +1 -1
- package/dist/errors.d.ts +12 -0
- package/dist/errors.js +14 -0
- package/dist/errors.js.map +1 -1
- package/dist/files/links.d.ts +10 -0
- package/dist/files/links.js +50 -0
- package/dist/files/links.js.map +1 -0
- package/dist/files/schema.d.ts +9 -0
- package/dist/files/schema.js +51 -0
- package/dist/files/schema.js.map +1 -0
- package/dist/index.d.ts +12 -2
- package/dist/index.js +12 -2
- package/dist/index.js.map +1 -1
- package/dist/kernel.d.ts +88 -0
- package/dist/kernel.js +82 -41
- package/dist/kernel.js.map +1 -1
- package/dist/mask.d.ts +7 -1
- package/dist/mask.js +11 -0
- package/dist/mask.js.map +1 -1
- package/dist/org.d.ts +7 -0
- package/dist/org.js +5 -0
- package/dist/org.js.map +1 -1
- package/dist/pipeline/draft.d.ts +16 -0
- package/dist/pipeline/draft.js +39 -0
- package/dist/pipeline/draft.js.map +1 -0
- package/dist/pipeline/idempotency.d.ts +6 -0
- package/dist/pipeline/idempotency.js +6 -0
- package/dist/pipeline/idempotency.js.map +1 -1
- package/dist/pipeline/invoker.d.ts +9 -0
- package/dist/pipeline/invoker.js +22 -0
- package/dist/pipeline/invoker.js.map +1 -0
- package/dist/pipeline/load.d.ts +13 -0
- package/dist/pipeline/load.js +22 -6
- package/dist/pipeline/load.js.map +1 -1
- package/dist/primitives/aggregate.d.ts +95 -2
- package/dist/primitives/aggregate.js +15 -1
- package/dist/primitives/aggregate.js.map +1 -1
- package/dist/primitives/business-process.d.ts +128 -0
- package/dist/primitives/business-process.js +62 -0
- package/dist/primitives/business-process.js.map +1 -0
- package/dist/primitives/collection.d.ts +65 -0
- package/dist/primitives/collection.js +79 -0
- package/dist/primitives/collection.js.map +1 -0
- package/dist/primitives/command.d.ts +110 -11
- package/dist/primitives/command.js +16 -0
- package/dist/primitives/command.js.map +1 -1
- package/dist/primitives/constraints.d.ts +30 -1
- package/dist/primitives/constraints.js +14 -0
- package/dist/primitives/constraints.js.map +1 -1
- package/dist/primitives/event.d.ts +36 -0
- package/dist/primitives/event.js +12 -1
- package/dist/primitives/event.js.map +1 -1
- package/dist/primitives/fields.d.ts +176 -36
- package/dist/primitives/fields.js +134 -14
- package/dist/primitives/fields.js.map +1 -1
- package/dist/primitives/flow.d.ts +173 -8
- package/dist/primitives/flow.js +29 -2
- package/dist/primitives/flow.js.map +1 -1
- package/dist/primitives/states.d.ts +34 -2
- package/dist/primitives/states.js +15 -0
- package/dist/primitives/states.js.map +1 -1
- package/dist/read.d.ts +39 -3
- package/dist/read.js +193 -48
- package/dist/read.js.map +1 -1
- package/dist/registry.d.ts +51 -1
- package/dist/registry.js +105 -5
- package/dist/registry.js.map +1 -1
- package/dist/relations.d.ts +21 -0
- package/dist/relations.js +65 -0
- package/dist/relations.js.map +1 -0
- package/dist/runtime.d.ts +35 -0
- package/dist/runtime.js +9 -0
- package/dist/runtime.js.map +1 -0
- package/dist/scope/index.d.ts +5 -0
- package/dist/scope/index.js +5 -0
- package/dist/scope/index.js.map +1 -1
- package/dist/telemetry.d.ts +8 -0
- package/dist/telemetry.js +28 -3
- package/dist/telemetry.js.map +1 -1
- package/dist/transfer/csv.d.ts +19 -0
- package/dist/transfer/csv.js +125 -0
- package/dist/transfer/csv.js.map +1 -0
- package/dist/transfer/index.d.ts +67 -0
- package/dist/transfer/index.js +271 -0
- package/dist/transfer/index.js.map +1 -0
- package/dist/transfer/schema.d.ts +9 -0
- package/dist/transfer/schema.js +36 -0
- package/dist/transfer/schema.js.map +1 -0
- package/dist/types.d.ts +38 -2
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -1
- package/dist/util/names.d.ts +6 -0
- package/dist/util/names.js +6 -0
- package/dist/util/names.js.map +1 -1
- package/dist/worker/consumers.d.ts +7 -0
- package/dist/worker/consumers.js +21 -9
- package/dist/worker/consumers.js.map +1 -1
- package/dist/worker/health.d.ts +38 -0
- package/dist/worker/health.js +20 -0
- package/dist/worker/health.js.map +1 -0
- package/dist/worker/index.d.ts +34 -1
- package/dist/worker/index.js +176 -37
- package/dist/worker/index.js.map +1 -1
- package/dist/worker/outbox.d.ts +25 -2
- package/dist/worker/outbox.js +40 -2
- package/dist/worker/outbox.js.map +1 -1
- package/dist/worker/scheduler.d.ts +10 -1
- package/dist/worker/scheduler.js +34 -4
- package/dist/worker/scheduler.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,19 +1,81 @@
|
|
|
1
1
|
# @yss123/cage-kernel
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Cage 的服务端内核:用 TypeScript 声明业务对象、状态、命令和事件,再统一执行权限、数据范围、版本、事务、审计与异步消息。适合有审批、组织权限和跨对象业务规则的中后台;它不是浏览器库,也不是绕过业务规则的通用表 CRUD。
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## 安装与位置
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
需要 Node.js 24+、PostgreSQL;框架包应使用同一版本。在应用的 domain 包中安装:
|
|
8
8
|
|
|
9
9
|
```powershell
|
|
10
|
-
pnpm add @yss123/cage-kernel
|
|
10
|
+
pnpm add @yss123/cage-kernel zod
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
新项目推荐 `pnpm create @yss123/cage-app my-app --template blank`,由模板配置 domain、API、worker、Web 与数据库连接。
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
- [框架源码与范例](https://github.com/shunshunyue/cage)
|
|
17
|
-
- [问题反馈](https://github.com/shunshunyue/cage/issues)
|
|
15
|
+
## 最小业务声明
|
|
18
16
|
|
|
19
|
-
|
|
17
|
+
在 `packages/domain/src/modules/note/note.ts` 中声明便笺。声明本身不连接数据库;handler 返回业务变化,由内核负责真正写入。
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
/** 部门便笺声明;经 domain 根入口注册,供 CLI 生成契约与 API 执行。 */
|
|
21
|
+
import { aggregate, command, ref, scope, states, text } from '@yss123/cage-kernel';
|
|
22
|
+
import { z } from 'zod';
|
|
23
|
+
|
|
24
|
+
/** 同部门范围的便笺;归属字段由内核依据当前主体补入,角色仍须显式授权。 */
|
|
25
|
+
export const Note = aggregate('Note', {
|
|
26
|
+
description: '部门便笺',
|
|
27
|
+
fields: {
|
|
28
|
+
title: text(120),
|
|
29
|
+
deptId: ref('Dept'),
|
|
30
|
+
createdBy: ref('User'),
|
|
31
|
+
},
|
|
32
|
+
states: states('active', 'archived', { terminal: ['archived'] }),
|
|
33
|
+
scope: scope.deptSubtree('deptId'),
|
|
34
|
+
invariants: { titleNotBlank: (note) => note.title.trim().length > 0 },
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
/** 创建有效便笺;输入规范化后进入草稿,权限、范围及最终不变量失败均不会提交。 */
|
|
38
|
+
export const createNote = command(Note, {
|
|
39
|
+
name: 'create',
|
|
40
|
+
description: '创建部门便笺',
|
|
41
|
+
from: 'new',
|
|
42
|
+
to: 'active',
|
|
43
|
+
input: z.object({ title: z.string().trim().min(1).max(120) }),
|
|
44
|
+
handler: (draft) => draft,
|
|
45
|
+
});
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
模块入口导出 `export * from './note.js';`,domain 根入口保留组织模型并导出新模块:
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
/** 组合所有可注册声明;未从这里导出的业务不会进入生成器和运行注册表。 */
|
|
52
|
+
export * from '@yss123/cage-admin/domain';
|
|
53
|
+
export * from './modules/note/index.js';
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
随后在应用根目录执行 `pnpm exec cage check`、`pnpm gen`;审查迁移后执行 `pnpm migrate`。管理员为目标角色授予 `Note.create`、`Note.read` 及 `Note` 数据范围,前端通过生成的 `@app/contracts` 调用 `note.create({ title })`、`note.list()`。
|
|
57
|
+
|
|
58
|
+
## 主要能力与边界
|
|
59
|
+
|
|
60
|
+
| 入口 | 用途 |
|
|
61
|
+
| --- | --- |
|
|
62
|
+
| `aggregate`、字段工厂、`states`、`scope` | 定义对象字段、关系、生命周期与范围字段 |
|
|
63
|
+
| `command`、`event`、`emit` | 定义唯一业务写入口及成功后产生的事实 |
|
|
64
|
+
| `reaction`、`reactionEach`、`job` | 同事务或异步协作、有界集合处理和定时任务 |
|
|
65
|
+
| `query`、`ReadSide` | 通过只读账号与 `safe.*` 安全视图读取 |
|
|
66
|
+
| `buildRegistry`、`createKernel` | 服务端集成时构建注册表和执行内核;普通应用交给 HTTP 装配 |
|
|
67
|
+
| `@yss123/cage-kernel/worker` | 底层 worker 启停、消费者和健康状态 |
|
|
68
|
+
| `@yss123/cage-kernel/db` | 迁移、DDL 与数据库基础设施,供工具链使用 |
|
|
69
|
+
| `@yss123/cage-kernel/brands` | 框架声明标识 |
|
|
70
|
+
|
|
71
|
+
handler 的读取写入 `reads`,任务的读取和命令调用写入 `reads/calls`。handler 不直接执行 SQL、HTTP 或文件 IO;外呼使用连接器。`scope` 声明不自动授权,前端 `can()` 不代替后端检查。`ref/hasMany/manyToMany` 统一写在 `fields`,集合关系由命令修改并通过安全读侧分页读取。
|
|
72
|
+
|
|
73
|
+
金额 `money()` 使用十进制字符串;不要重复定义框架的 `id/version/status/createdAt/updatedAt/tenantId`。新结构用新迁移表达,服务启动不自动建库、迁移或初始化账号。
|
|
74
|
+
|
|
75
|
+
## 继续阅读
|
|
76
|
+
|
|
77
|
+
- [架构与执行模型](https://github.com/shunshunyue/cage/blob/main/docs/ai/architecture.md)
|
|
78
|
+
- [原语、命令与查询](https://github.com/shunshunyue/cage/blob/main/docs/ai/primitives.md)
|
|
79
|
+
- [对象关系](https://github.com/shunshunyue/cage/blob/main/docs/ai/relations.md)
|
|
80
|
+
|
|
81
|
+
脚手架项目自带 `docs/ai` 与 `docs/errors`,可离线学习。源码与反馈:[GitHub](https://github.com/shunshunyue/cage)。许可证:[MIT](https://github.com/shunshunyue/cage/blob/main/LICENSE)。
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { Kernel } from './kernel.js';
|
|
2
|
+
import type { Ctx } from './types.js';
|
|
3
|
+
/** not-inspected 表示证据不足,与 fail、pass 分开,避免把未检查结果误当成功。 */
|
|
4
|
+
export interface AuthorizationCheck {
|
|
5
|
+
stage: string;
|
|
6
|
+
status: 'pass' | 'fail' | 'not-inspected';
|
|
7
|
+
code?: string;
|
|
8
|
+
reason?: unknown;
|
|
9
|
+
}
|
|
10
|
+
/** 无 handler、无锁、无写入;可解释的判断复用实际身份、范围和约束实现。结果仅代表观测时刻。 */
|
|
11
|
+
/**
|
|
12
|
+
* 先检查输入和主体,再在只读事务中检查对象可见性、状态、版本及硬约束。
|
|
13
|
+
* 新建最终范围依赖 handler,约束依赖异常也不可判定:二者均返回 allowed:null 所需的未知证据。
|
|
14
|
+
* 已确认拒绝优先返回 false;返回的 observedAt 标记时效,实际执行仍会重新鉴权和加锁。
|
|
15
|
+
*/
|
|
16
|
+
export declare function explainAuthorization(k: Kernel, capability: string, raw: Record<string, unknown>, ctx: Ctx): Promise<{
|
|
17
|
+
command: string;
|
|
18
|
+
actor: import("./types.js").Actor | null;
|
|
19
|
+
observedAt: string;
|
|
20
|
+
allowed: boolean;
|
|
21
|
+
checks: AuthorizationCheck[];
|
|
22
|
+
scope?: undefined;
|
|
23
|
+
params?: undefined;
|
|
24
|
+
limitations?: undefined;
|
|
25
|
+
} | {
|
|
26
|
+
command: string;
|
|
27
|
+
actor: import("./types.js").Actor | null;
|
|
28
|
+
observedAt: string;
|
|
29
|
+
allowed: boolean | null;
|
|
30
|
+
checks: AuthorizationCheck[];
|
|
31
|
+
scope: import("./types.js").ScopeGrant[];
|
|
32
|
+
params: import("./types.js").CapabilityParams;
|
|
33
|
+
limitations: string[];
|
|
34
|
+
}>;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 权限解释器只收集观测证据,不执行 handler、写审计或抢锁。
|
|
3
|
+
* 它复用真实输入、调用身份、范围及约束检查;输出不能当作后续执行的授权凭证。
|
|
4
|
+
*/
|
|
5
|
+
import { cageError, toCageError } from './errors.js';
|
|
6
|
+
import { loadUserGrants } from './org.js';
|
|
7
|
+
import { assertInvoker } from './pipeline/invoker.js';
|
|
8
|
+
import { loadScoped } from './pipeline/load.js';
|
|
9
|
+
import { newDraft, splitRaw } from './pipeline/draft.js';
|
|
10
|
+
/** 固定公开文案代替任意自定义约束消息,防止消息中拼接的业务明文穿过诊断边界。 */
|
|
11
|
+
function constraintReason(name) {
|
|
12
|
+
if (name.startsWith('ceiling('))
|
|
13
|
+
return '额度未配置或不足;请检查该能力的有效参数';
|
|
14
|
+
if (name.startsWith('sod.notSameAs('))
|
|
15
|
+
return '职责分离条件未满足';
|
|
16
|
+
if (name === 'stepUp')
|
|
17
|
+
return '需要近期二次认证';
|
|
18
|
+
return '硬约束未满足;请按约束名称检查规则';
|
|
19
|
+
}
|
|
20
|
+
/** 无 handler、无锁、无写入;可解释的判断复用实际身份、范围和约束实现。结果仅代表观测时刻。 */
|
|
21
|
+
/**
|
|
22
|
+
* 先检查输入和主体,再在只读事务中检查对象可见性、状态、版本及硬约束。
|
|
23
|
+
* 新建最终范围依赖 handler,约束依赖异常也不可判定:二者均返回 allowed:null 所需的未知证据。
|
|
24
|
+
* 已确认拒绝优先返回 false;返回的 observedAt 标记时效,实际执行仍会重新鉴权和加锁。
|
|
25
|
+
*/
|
|
26
|
+
export async function explainAuthorization(k, capability, raw, ctx) {
|
|
27
|
+
const rc = k.registry.command(capability);
|
|
28
|
+
if (!rc)
|
|
29
|
+
throw cageError('NOT_FOUND');
|
|
30
|
+
const cmd = rc.cmd, checks = [];
|
|
31
|
+
const add = (stage, allowed, code, reason) => checks.push({ stage, status: allowed ? 'pass' : 'fail', code: allowed ? undefined : code, reason });
|
|
32
|
+
add('authentication', !!ctx.actor && (ctx.actor.kind !== 'anonymous' || cmd.public), 'UNAUTHENTICATED');
|
|
33
|
+
let split;
|
|
34
|
+
try {
|
|
35
|
+
split = splitRaw(raw);
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
const result = toCageError(error);
|
|
39
|
+
checks.push({ stage: 'input', status: 'fail', code: result.code, reason: result.detail });
|
|
40
|
+
return { command: capability, actor: ctx.actor, observedAt: new Date().toISOString(), allowed: false, checks };
|
|
41
|
+
}
|
|
42
|
+
const { expectedVersion, rest } = split;
|
|
43
|
+
const parsed = cmd.input.safeParse(rest);
|
|
44
|
+
add('input', parsed.success, 'INVALID_INPUT', parsed.success ? undefined : parsed.error.issues.map((issue) => ({ path: issue.path.join('.'), message: issue.message })));
|
|
45
|
+
try {
|
|
46
|
+
if (ctx.actor)
|
|
47
|
+
assertInvoker(cmd, ctx, capability);
|
|
48
|
+
else
|
|
49
|
+
throw cageError('UNAUTHENTICATED');
|
|
50
|
+
add('invoker', true);
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
const result = toCageError(error);
|
|
54
|
+
add('invoker', false, result.code, result.detail);
|
|
55
|
+
}
|
|
56
|
+
add('capability', cmd.public || ctx.capabilities.has(capability), 'FORBIDDEN', { capability });
|
|
57
|
+
if (checks.every((check) => check.status === 'pass'))
|
|
58
|
+
await k.app.transaction().setAccessMode('read only').execute(async (tx) => {
|
|
59
|
+
const parsedInput = parsed.data;
|
|
60
|
+
const current = cmd.from === 'new' ? newDraft(cmd, parsedInput, ctx, new Date()) : typeof parsedInput.id === 'string' ? await loadScoped(tx, cmd.agg, parsedInput.id, ctx, false) : null;
|
|
61
|
+
if (cmd.from === 'new')
|
|
62
|
+
checks.push({ stage: 'scope', status: 'not-inspected', reason: '新建最终范围要在 handler 合并后实际校验;诊断不执行 handler' });
|
|
63
|
+
else
|
|
64
|
+
add('scope', !!current, 'NOT_FOUND', current ? undefined : '对象不存在或不在有效范围内');
|
|
65
|
+
if (!current)
|
|
66
|
+
return;
|
|
67
|
+
add('state', cmd.from === 'new' || cmd.from.includes(current.status), 'INVALID_TRANSITION');
|
|
68
|
+
add('version', cmd.from === 'new' || expectedVersion === undefined || expectedVersion === current.version, 'CONFLICT');
|
|
69
|
+
const meta = {
|
|
70
|
+
capability, capabilitiesOf: async (id) => (await loadUserGrants(tx, id, ctx.tenantId))?.capabilities ?? new Map(),
|
|
71
|
+
load: async (name, id) => { const agg = k.registry.aggregate(name); return agg ? loadScoped(tx, agg, id, ctx, false) : null; },
|
|
72
|
+
catalog: () => k.catalogCaps(),
|
|
73
|
+
};
|
|
74
|
+
for (const constraint of cmd.constraints) {
|
|
75
|
+
// 自定义 message 可能拼入未解掩码的字段或关联对象值,诊断只返回固定说明与规则名称。
|
|
76
|
+
try {
|
|
77
|
+
const result = await constraint.check(current, ctx, parsed.data, meta);
|
|
78
|
+
add(`constraint:${constraint.name}`, result.ok, 'CONSTRAINT_VIOLATED', result.ok ? undefined : constraintReason(constraint.name));
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
checks.push({ stage: `constraint:${constraint.name}`, status: 'not-inspected', reason: '约束检查依赖不可用,不能判定通过' });
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
return { command: capability, actor: ctx.actor, observedAt: new Date().toISOString(), allowed: checks.some((check) => check.status === 'fail') ? false : checks.some((check) => check.status === 'not-inspected') ? null : true, checks,
|
|
86
|
+
scope: ctx.scopes[cmd.agg.name] ?? ctx.scopes['*'] ?? [{ combinator: 'self' }], params: ctx.capabilities.get(capability) ?? {},
|
|
87
|
+
limitations: ['只解释认证、输入、调用身份、能力、范围、状态、版本和硬约束;不执行 handler 或预测最终不变量。', '执行时会重新鉴权和加锁,诊断结果不能用于跳过实际授权。'] };
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=authorization.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authorization.js","sourceRoot":"","sources":["../src/authorization.ts"],"names":[],"mappings":"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"}
|
package/dist/brands.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/** 持久化对象声明;注册表据此收集字段、状态、范围和不变量。 */
|
|
1
2
|
export declare const AGGREGATE: unique symbol;
|
|
2
3
|
export declare const STATES: unique symbol;
|
|
3
4
|
export declare const COMMAND: unique symbol;
|
|
@@ -6,6 +7,7 @@ export declare const REACTION: unique symbol;
|
|
|
6
7
|
export declare const QUERY: unique symbol;
|
|
7
8
|
export declare const APPROVAL: unique symbol;
|
|
8
9
|
export declare const JOB: unique symbol;
|
|
10
|
+
export declare const BUSINESS_PROCESS: unique symbol;
|
|
9
11
|
export declare const UNSAFE: unique symbol;
|
|
10
12
|
export declare const CONNECTOR: unique symbol;
|
|
11
13
|
export declare const OUTBOUND: unique symbol;
|
|
@@ -13,6 +15,12 @@ export declare const INBOUND: unique symbol;
|
|
|
13
15
|
export declare const ROUTE: unique symbol;
|
|
14
16
|
export declare const CONSUMERS: unique symbol;
|
|
15
17
|
export declare const SYSTEM_DDL: unique symbol;
|
|
18
|
+
export declare const RUNTIME: unique symbol;
|
|
19
|
+
export declare const MIGRATIONS: unique symbol;
|
|
20
|
+
/**
|
|
21
|
+
* 领域声明的识别目录。这里不包含 CONSUMERS、SYSTEM_DDL 等扩展协议标记:
|
|
22
|
+
* 它们描述声明附带的能力,不是一个独立业务节点,避免抽取时将同一对象重复分类。
|
|
23
|
+
*/
|
|
16
24
|
export declare const ALL_BRANDS: {
|
|
17
25
|
readonly AGGREGATE: typeof AGGREGATE;
|
|
18
26
|
readonly STATES: typeof STATES;
|
|
@@ -22,6 +30,7 @@ export declare const ALL_BRANDS: {
|
|
|
22
30
|
readonly QUERY: typeof QUERY;
|
|
23
31
|
readonly APPROVAL: typeof APPROVAL;
|
|
24
32
|
readonly JOB: typeof JOB;
|
|
33
|
+
readonly BUSINESS_PROCESS: typeof BUSINESS_PROCESS;
|
|
25
34
|
readonly UNSAFE: typeof UNSAFE;
|
|
26
35
|
readonly CONNECTOR: typeof CONNECTOR;
|
|
27
36
|
readonly OUTBOUND: typeof OUTBOUND;
|
|
@@ -29,4 +38,5 @@ export declare const ALL_BRANDS: {
|
|
|
29
38
|
readonly ROUTE: typeof ROUTE;
|
|
30
39
|
};
|
|
31
40
|
/** 判断一个值属于哪种原语;不是原语返回 null。 */
|
|
41
|
+
/** 只读取标记,不执行声明中的回调;可安全用于模块导出的混合值筛选。 */
|
|
32
42
|
export declare function brandOf(v: unknown): keyof typeof ALL_BRANDS | null;
|
package/dist/brands.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// 品牌标记:抽取器、注册表和内核靠它们识别原语返回的描述对象。
|
|
2
2
|
// 使用 Symbol.for,即使同一个包被加载两份,标记也相同。
|
|
3
|
+
/** 持久化对象声明;注册表据此收集字段、状态、范围和不变量。 */
|
|
3
4
|
export const AGGREGATE = Symbol.for('cage.aggregate');
|
|
4
5
|
export const STATES = Symbol.for('cage.states');
|
|
5
6
|
export const COMMAND = Symbol.for('cage.command');
|
|
@@ -8,6 +9,7 @@ export const REACTION = Symbol.for('cage.reaction');
|
|
|
8
9
|
export const QUERY = Symbol.for('cage.query');
|
|
9
10
|
export const APPROVAL = Symbol.for('cage.approval');
|
|
10
11
|
export const JOB = Symbol.for('cage.job');
|
|
12
|
+
export const BUSINESS_PROCESS = Symbol.for('cage.businessProcess');
|
|
11
13
|
export const UNSAFE = Symbol.for('cage.unsafe');
|
|
12
14
|
// 以下原语由 @yss123/cage-connectors、@yss123/cage-approval 实现,标记放在这里统一管理
|
|
13
15
|
export const CONNECTOR = Symbol.for('cage.connector');
|
|
@@ -18,11 +20,19 @@ export const ROUTE = Symbol.for('cage.route');
|
|
|
18
20
|
export const CONSUMERS = Symbol.for('cage.consumers');
|
|
19
21
|
// 运行时扩展点:带这个标记的声明对象可以提供框架自己的系统表 DDL
|
|
20
22
|
export const SYSTEM_DDL = Symbol.for('cage.systemDdl');
|
|
23
|
+
// 基础设施扩展,不增加领域原语:服务自行提供迁移、HTTP 与后台处理器。
|
|
24
|
+
export const RUNTIME = Symbol.for('cage.runtime');
|
|
25
|
+
export const MIGRATIONS = Symbol.for('cage.migrations');
|
|
26
|
+
/**
|
|
27
|
+
* 领域声明的识别目录。这里不包含 CONSUMERS、SYSTEM_DDL 等扩展协议标记:
|
|
28
|
+
* 它们描述声明附带的能力,不是一个独立业务节点,避免抽取时将同一对象重复分类。
|
|
29
|
+
*/
|
|
21
30
|
export const ALL_BRANDS = {
|
|
22
|
-
AGGREGATE, STATES, COMMAND, EVENT, REACTION, QUERY, APPROVAL, JOB, UNSAFE,
|
|
31
|
+
AGGREGATE, STATES, COMMAND, EVENT, REACTION, QUERY, APPROVAL, JOB, BUSINESS_PROCESS, UNSAFE,
|
|
23
32
|
CONNECTOR, OUTBOUND, INBOUND, ROUTE,
|
|
24
33
|
};
|
|
25
34
|
/** 判断一个值属于哪种原语;不是原语返回 null。 */
|
|
35
|
+
/** 只读取标记,不执行声明中的回调;可安全用于模块导出的混合值筛选。 */
|
|
26
36
|
export function brandOf(v) {
|
|
27
37
|
if (!v || (typeof v !== 'object' && typeof v !== 'function'))
|
|
28
38
|
return null;
|
package/dist/brands.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"brands.js","sourceRoot":"","sources":["../src/brands.ts"],"names":[],"mappings":"AAAA,iCAAiC;AACjC,mCAAmC;AAEnC,MAAM,CAAC,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;AACtD,MAAM,CAAC,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;AAChD,MAAM,CAAC,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;AAClD,MAAM,CAAC,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;AAC9C,MAAM,CAAC,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;AACpD,MAAM,CAAC,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;AAC9C,MAAM,CAAC,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;AACpD,MAAM,CAAC,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;AAC1C,MAAM,CAAC,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;AAChD,oEAAoE;AACpE,MAAM,CAAC,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;AACtD,MAAM,CAAC,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;AACpD,MAAM,CAAC,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;AAClD,MAAM,CAAC,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;AAE9C,sCAAsC;AACtC,MAAM,CAAC,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;AACtD,oCAAoC;AACpC,MAAM,CAAC,MAAM,UAAU,GAAG,MAAM,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"brands.js","sourceRoot":"","sources":["../src/brands.ts"],"names":[],"mappings":"AAAA,iCAAiC;AACjC,mCAAmC;AAEnC,mCAAmC;AACnC,MAAM,CAAC,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;AACtD,MAAM,CAAC,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;AAChD,MAAM,CAAC,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;AAClD,MAAM,CAAC,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;AAC9C,MAAM,CAAC,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;AACpD,MAAM,CAAC,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;AAC9C,MAAM,CAAC,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;AACpD,MAAM,CAAC,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;AAC1C,MAAM,CAAC,MAAM,gBAAgB,GAAG,MAAM,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;AACnE,MAAM,CAAC,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;AAChD,oEAAoE;AACpE,MAAM,CAAC,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;AACtD,MAAM,CAAC,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;AACpD,MAAM,CAAC,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;AAClD,MAAM,CAAC,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;AAE9C,sCAAsC;AACtC,MAAM,CAAC,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;AACtD,oCAAoC;AACpC,MAAM,CAAC,MAAM,UAAU,GAAG,MAAM,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;AACvD,uCAAuC;AACvC,MAAM,CAAC,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;AAClD,MAAM,CAAC,MAAM,UAAU,GAAG,MAAM,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;AAExD;;;GAGG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,gBAAgB,EAAE,MAAM;IAC3F,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK;CAC3B,CAAC;AAEX,+BAA+B;AAC/B,uCAAuC;AACvC,MAAM,UAAU,OAAO,CAAC,CAAU;IAChC,IAAI,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,OAAO,CAAC,KAAK,UAAU,CAAC;QAAE,OAAO,IAAI,CAAC;IAC1E,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;QAChD,IAAK,CAAS,CAAC,CAAC,CAAC;YAAE,OAAO,CAA4B,CAAC;IACzD,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
package/dist/db/connect.d.ts
CHANGED
|
@@ -1,16 +1,26 @@
|
|
|
1
1
|
import { Kysely } from 'kysely';
|
|
2
2
|
import pg from 'pg';
|
|
3
|
+
/** 内核自建连接的所有权句柄;close 销毁 Kysely 及底层池,调用方不应继续复用它。 */
|
|
3
4
|
export interface DbHandle {
|
|
4
5
|
db: Kysely<any>;
|
|
5
6
|
pool: pg.Pool;
|
|
6
7
|
close(): Promise<void>;
|
|
7
8
|
}
|
|
9
|
+
/**
|
|
10
|
+
* 创建一个独立账号的连接池,所有超时均以毫秒计;构造池不等于已验证数据库可连通。
|
|
11
|
+
* 读账号与写账号分别建池,避免会话权限混用。onConnect 是连接事件钩子,不承担迁移或账号初始化。
|
|
12
|
+
* 默认的连接、语句、空闲事务时限让池耗尽和遗留事务可失败退出,不能用无限等待隐藏锁问题。
|
|
13
|
+
*/
|
|
8
14
|
export declare function connect(url: string, opts?: {
|
|
9
15
|
max?: number;
|
|
10
16
|
onConnect?: (c: pg.PoolClient) => Promise<void>;
|
|
11
17
|
applicationName?: string;
|
|
18
|
+
connectionTimeoutMs?: number;
|
|
19
|
+
statementTimeoutMs?: number;
|
|
20
|
+
idleTransactionTimeoutMs?: number;
|
|
12
21
|
}): DbHandle;
|
|
13
22
|
/** 单独的长连接(LISTEN、咨询锁用),不进连接池 */
|
|
23
|
+
/** 成功返回已连接客户端;调用方必须 end,并在网络断开时重建 LISTEN/咨询锁状态。 */
|
|
14
24
|
export declare function dedicatedClient(url: string, applicationName?: string): Promise<pg.Client>;
|
|
15
25
|
export interface DatabaseUrls {
|
|
16
26
|
/** 内核账号 cage_app */
|
|
@@ -25,4 +35,8 @@ export interface DatabaseUrls {
|
|
|
25
35
|
* CAGE_APP_DATABASE_URL / CAGE_READ_DATABASE_URL / CAGE_MIGRATE_DATABASE_URL
|
|
26
36
|
* 或只给一个 DATABASE_URL(主机、端口、库名),各账号用默认用户名和 CAGE_DB_PASSWORD。
|
|
27
37
|
*/
|
|
38
|
+
/**
|
|
39
|
+
* 专用连接串优先于 DATABASE_URL 派生值;仅解析配置,不创建数据库、角色或重置密码。
|
|
40
|
+
* 返回值含凭据,应只传给连接层,排障时提取主机/端口/库名而不要输出整个对象。
|
|
41
|
+
*/
|
|
28
42
|
export declare function urlsFromEnv(env?: NodeJS.ProcessEnv): DatabaseUrls;
|
package/dist/db/connect.js
CHANGED
|
@@ -12,8 +12,19 @@ const types = {
|
|
|
12
12
|
return p ?? pg.types.getTypeParser(oid, format);
|
|
13
13
|
},
|
|
14
14
|
};
|
|
15
|
+
/**
|
|
16
|
+
* 创建一个独立账号的连接池,所有超时均以毫秒计;构造池不等于已验证数据库可连通。
|
|
17
|
+
* 读账号与写账号分别建池,避免会话权限混用。onConnect 是连接事件钩子,不承担迁移或账号初始化。
|
|
18
|
+
* 默认的连接、语句、空闲事务时限让池耗尽和遗留事务可失败退出,不能用无限等待隐藏锁问题。
|
|
19
|
+
*/
|
|
15
20
|
export function connect(url, opts = {}) {
|
|
16
|
-
|
|
21
|
+
// 池耗尽和遗留事务都必须有界;加大连接池不能修复持有连接再等待同池连接的循环。
|
|
22
|
+
const pool = new pg.Pool({
|
|
23
|
+
connectionString: url, max: opts.max ?? 10, types: types, application_name: opts.applicationName ?? 'cage',
|
|
24
|
+
connectionTimeoutMillis: opts.connectionTimeoutMs ?? 5_000,
|
|
25
|
+
statement_timeout: opts.statementTimeoutMs ?? 30_000,
|
|
26
|
+
idle_in_transaction_session_timeout: opts.idleTransactionTimeoutMs ?? 30_000,
|
|
27
|
+
});
|
|
17
28
|
if (opts.onConnect)
|
|
18
29
|
pool.on('connect', (c) => void opts.onConnect(c));
|
|
19
30
|
const db = new Kysely({ dialect: new PostgresDialect({ pool }) });
|
|
@@ -26,8 +37,9 @@ export function connect(url, opts = {}) {
|
|
|
26
37
|
};
|
|
27
38
|
}
|
|
28
39
|
/** 单独的长连接(LISTEN、咨询锁用),不进连接池 */
|
|
40
|
+
/** 成功返回已连接客户端;调用方必须 end,并在网络断开时重建 LISTEN/咨询锁状态。 */
|
|
29
41
|
export async function dedicatedClient(url, applicationName = 'cage-listener') {
|
|
30
|
-
const c = new pg.Client({ connectionString: url, types: types, application_name: applicationName });
|
|
42
|
+
const c = new pg.Client({ connectionString: url, types: types, application_name: applicationName, connectionTimeoutMillis: 5_000, statement_timeout: 30_000 });
|
|
31
43
|
await c.connect();
|
|
32
44
|
return c;
|
|
33
45
|
}
|
|
@@ -36,6 +48,10 @@ export async function dedicatedClient(url, applicationName = 'cage-listener') {
|
|
|
36
48
|
* CAGE_APP_DATABASE_URL / CAGE_READ_DATABASE_URL / CAGE_MIGRATE_DATABASE_URL
|
|
37
49
|
* 或只给一个 DATABASE_URL(主机、端口、库名),各账号用默认用户名和 CAGE_DB_PASSWORD。
|
|
38
50
|
*/
|
|
51
|
+
/**
|
|
52
|
+
* 专用连接串优先于 DATABASE_URL 派生值;仅解析配置,不创建数据库、角色或重置密码。
|
|
53
|
+
* 返回值含凭据,应只传给连接层,排障时提取主机/端口/库名而不要输出整个对象。
|
|
54
|
+
*/
|
|
39
55
|
export function urlsFromEnv(env = process.env) {
|
|
40
56
|
const base = env.DATABASE_URL;
|
|
41
57
|
const derive = (user, pwVar) => {
|
package/dist/db/connect.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connect.js","sourceRoot":"","sources":["../../src/db/connect.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAC;AACjD,OAAO,EAAE,MAAM,IAAI,CAAC;AAEpB,4DAA4D;AAC5D,MAAM,OAAO,GAA2C;IACtD,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,OAAO;IAC7B,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,OAAO;CACxB,CAAC;AAEF,MAAM,KAAK,GAAG;IACZ,aAAa,CAAC,GAAW,EAAE,MAAY;QACrC,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QACvB,OAAO,CAAC,IAAK,EAAE,CAAC,KAAK,CAAC,aAAqB,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IAC3D,CAAC;CACF,CAAC;
|
|
1
|
+
{"version":3,"file":"connect.js","sourceRoot":"","sources":["../../src/db/connect.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAC;AACjD,OAAO,EAAE,MAAM,IAAI,CAAC;AAEpB,4DAA4D;AAC5D,MAAM,OAAO,GAA2C;IACtD,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,OAAO;IAC7B,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,OAAO;CACxB,CAAC;AAEF,MAAM,KAAK,GAAG;IACZ,aAAa,CAAC,GAAW,EAAE,MAAY;QACrC,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QACvB,OAAO,CAAC,IAAK,EAAE,CAAC,KAAK,CAAC,aAAqB,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IAC3D,CAAC;CACF,CAAC;AASF;;;;GAIG;AACH,MAAM,UAAU,OAAO,CACrB,GAAW,EACX,OAAkM,EAAE;IAEpM,yCAAyC;IACzC,MAAM,IAAI,GAAG,IAAI,EAAE,CAAC,IAAI,CAAC;QACvB,gBAAgB,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,IAAI,EAAE,EAAE,KAAK,EAAE,KAAY,EAAE,gBAAgB,EAAE,IAAI,CAAC,eAAe,IAAI,MAAM;QACjH,uBAAuB,EAAE,IAAI,CAAC,mBAAmB,IAAI,KAAK;QAC1D,iBAAiB,EAAE,IAAI,CAAC,kBAAkB,IAAI,MAAM;QACpD,mCAAmC,EAAE,IAAI,CAAC,wBAAwB,IAAI,MAAM;KAC7E,CAAC,CAAC;IACH,IAAI,IAAI,CAAC,SAAS;QAAE,IAAI,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,IAAI,CAAC,SAAU,CAAC,CAAC,CAAC,CAAC,CAAC;IACvE,MAAM,EAAE,GAAG,IAAI,MAAM,CAAM,EAAE,OAAO,EAAE,IAAI,eAAe,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;IACvE,OAAO;QACL,EAAE;QACF,IAAI;QACJ,KAAK,EAAE,KAAK,IAAI,EAAE;YAChB,MAAM,EAAE,CAAC,OAAO,EAAE,CAAC;QACrB,CAAC;KACF,CAAC;AACJ,CAAC;AAED,gCAAgC;AAChC,mDAAmD;AACnD,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,GAAW,EAAE,eAAe,GAAG,eAAe;IAClF,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC,MAAM,CAAC,EAAE,gBAAgB,EAAE,GAAG,EAAE,KAAK,EAAE,KAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,uBAAuB,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,EAAE,CAAC,CAAC;IACtK,MAAM,CAAC,CAAC,OAAO,EAAE,CAAC;IAClB,OAAO,CAAC,CAAC;AACX,CAAC;AAWD;;;;GAIG;AACH;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,MAAyB,OAAO,CAAC,GAAG;IAC9D,MAAM,IAAI,GAAG,GAAG,CAAC,YAAY,CAAC;IAC9B,MAAM,MAAM,GAAG,CAAC,IAAY,EAAE,KAAa,EAAE,EAAE;QAC7C,IAAI,CAAC,IAAI;YAAE,OAAO,SAAS,CAAC;QAC5B,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC;QACxB,CAAC,CAAC,QAAQ,GAAG,IAAI,CAAC;QAClB,CAAC,CAAC,QAAQ,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,gBAAgB,IAAI,IAAI,CAAC;QACxD,OAAO,CAAC,CAAC,QAAQ,EAAE,CAAC;IACtB,CAAC,CAAC;IACF,MAAM,GAAG,GAAG,GAAG,CAAC,qBAAqB,IAAI,MAAM,CAAC,UAAU,EAAE,mBAAmB,CAAC,CAAC;IACjF,MAAM,IAAI,GAAG,GAAG,CAAC,sBAAsB,IAAI,MAAM,CAAC,WAAW,EAAE,oBAAoB,CAAC,CAAC;IACrF,MAAM,OAAO,GAAG,GAAG,CAAC,yBAAyB,IAAI,MAAM,CAAC,cAAc,EAAE,uBAAuB,CAAC,CAAC;IACjG,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAClB,MAAM,IAAI,KAAK,CAAC,yFAAyF,CAAC,CAAC;IAC7G,CAAC;IACD,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AAChC,CAAC"}
|
package/dist/db/ddl.d.ts
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import type { AnyAggregate } from '../primitives/aggregate.js';
|
|
2
2
|
import type { Registry } from '../registry.js';
|
|
3
|
+
/** SQL 标识符引用,双引号转义;仅用于已由声明验证的名称,不接受任意 SQL 片段。 */
|
|
3
4
|
export declare const q: (ident: string) => string;
|
|
5
|
+
/** 模式和表名分别引用,避免把含点名称误当成一个未限定标识符。 */
|
|
4
6
|
export declare const qt: (t: {
|
|
5
7
|
schema: string;
|
|
6
8
|
name: string;
|
|
7
9
|
}) => string;
|
|
10
|
+
/** 可序列化物理列规格;它描述期望结构,迁移执行前还需审查旧数据兼容性。 */
|
|
8
11
|
export interface ColumnModel {
|
|
9
12
|
name: string;
|
|
10
13
|
type: string;
|
|
@@ -15,48 +18,84 @@ export interface ColumnModel {
|
|
|
15
18
|
/** 枚举取值(CHECK 约束) */
|
|
16
19
|
values?: string[];
|
|
17
20
|
}
|
|
21
|
+
/** 普通聚合表与自动关联表共享模型;relation 存在时没有普通聚合的状态和版本语义。 */
|
|
18
22
|
export interface TableModel {
|
|
19
23
|
schema: string;
|
|
20
24
|
name: string;
|
|
21
25
|
aggregate: string;
|
|
22
26
|
columns: ColumnModel[];
|
|
23
27
|
statusValues: string[];
|
|
24
|
-
/**
|
|
28
|
+
/** 索引也表达租户复合唯一键,供自动关系表的复合外键引用。 */
|
|
25
29
|
indexes: {
|
|
26
30
|
name: string;
|
|
27
31
|
columns: string[];
|
|
32
|
+
unique?: boolean;
|
|
28
33
|
}[];
|
|
34
|
+
/** 物理关联表不是聚合:没有状态、版本、独立命令和能力点。 */
|
|
35
|
+
relation?: {
|
|
36
|
+
field: string;
|
|
37
|
+
source: string;
|
|
38
|
+
target: string;
|
|
39
|
+
};
|
|
29
40
|
}
|
|
41
|
+
/** 随迁移嵌入的结构快照,version 是此序列化格式版本,不是应用或数据库迁移号。 */
|
|
30
42
|
export interface SchemaModel {
|
|
31
43
|
version: 1;
|
|
32
44
|
tables: TableModel[];
|
|
33
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* 从字段/状态/范围生成主表列和索引,集合关系不作为主表列。
|
|
48
|
+
* 参与 manyToMany 的主表补租户/id 复合唯一键,让关联外键在数据库层保证双方租户一致。
|
|
49
|
+
*/
|
|
34
50
|
export declare function tableModel(agg: AnyAggregate, reg: Registry): TableModel;
|
|
35
51
|
/** 按外键依赖排序:被引用的表在前 */
|
|
36
52
|
export declare function schemaModel(reg: Registry): SchemaModel;
|
|
53
|
+
/**
|
|
54
|
+
* 生成建表与索引 SQL,不执行它。普通表创建状态约束,关联表创建租户复合主键和双方外键。
|
|
55
|
+
* 仅关联表授予删除链接权限;普通业务对象的删除仍应由命令状态迁移表达。
|
|
56
|
+
*/
|
|
37
57
|
export declare function createTableSql(t: TableModel): string;
|
|
38
58
|
/**
|
|
39
59
|
* 比较两份结构,生成迁移草稿语句。破坏性变更(删表、删列)只生成注释,按「先扩展再收缩」由人决定。
|
|
40
60
|
*/
|
|
61
|
+
/**
|
|
62
|
+
* prev 为迁移中的历史期望快照,null 表示首次建表;这里不会连接数据库扫描实际结构。
|
|
63
|
+
* 非空新增列和类型变化会生成待审查步骤,删除只给注释;自动草稿不保证既有数据能够直接迁移。
|
|
64
|
+
*/
|
|
41
65
|
export declare function diffSchemas(prev: SchemaModel | null, next: SchemaModel): string[];
|
|
66
|
+
/** 数据库范围函数与 scope/index.ts 保持同口径;缺少身份/授权会保守拒绝,不默认开放全部。 */
|
|
42
67
|
export declare const IN_SCOPE_SQL = "\n-- \u751F\u6210\u7269\uFF1A\u8303\u56F4\u5224\u65AD\u3002\u8BFB\u53D6\u4F1A\u8BDD\u53D8\u91CF app.scopes\uFF08{\"\u805A\u5408\":[{\"c\":\"\u7EC4\u5408\u5B50\",\"deptIds\":[...]}]}\uFF09\uFF0C\u591A\u4E2A\u6388\u6743\u53D6\u5E76\u96C6\u3002\n-- SECURITY DEFINER\uFF1A\u4EE5\u8868\u5C5E\u4E3B\u8EAB\u4EFD\u8BFB\u90E8\u95E8\u8868\uFF0C\u907F\u514D\u90E8\u95E8\u8868\u81EA\u5DF1\u7684\u884C\u7EA7\u7B56\u7565\u9012\u5F52\u3002\nCREATE OR REPLACE FUNCTION sys.in_scope(agg text, dept uuid, owner uuid)\nRETURNS boolean LANGUAGE sql STABLE SECURITY DEFINER SET search_path = pg_catalog, sys AS $$\n SELECT coalesce(bool_or(\n CASE g->>'c'\n WHEN 'all' THEN true\n WHEN 'self' THEN owner IS NOT NULL AND owner = nullif(current_setting('app.user_id', true), '')::uuid\n WHEN 'dept' THEN dept IS NOT NULL AND dept = nullif(current_setting('app.dept_id', true), '')::uuid\n WHEN 'deptSubtree' THEN dept IN (\n SELECT d.id FROM sys.dept d\n WHERE d.ancestors LIKE nullif(current_setting('app.dept_path', true), '') || '%')\n WHEN 'deptSet' THEN dept = ANY (ARRAY(SELECT jsonb_array_elements_text(coalesce(g->'deptIds', '[]'::jsonb)))::uuid[])\n ELSE false\n END), false)\n FROM jsonb_array_elements(coalesce(\n nullif(current_setting('app.scopes', true), '')::jsonb -> agg,\n nullif(current_setting('app.scopes', true), '')::jsonb -> '*',\n '[{\"c\":\"self\"}]'::jsonb)) AS g\n$$;";
|
|
68
|
+
/** 安全视图使用的字段掩码函数;明文权限来自事务会话变量,展示策略须与内存 maskValue 一致。 */
|
|
43
69
|
export declare const MASK_SQL = "\n-- \u751F\u6210\u7269\uFF1A\u6309\u654F\u611F\u79CD\u7C7B\u63A9\u7801\u3002\u6301\u6709\u300C\u805A\u5408.\u79CD\u7C7B\u300D\u660E\u6587\u6743\u9650\u65F6\u539F\u6837\u8FD4\u56DE\u3002\nCREATE OR REPLACE FUNCTION sys.mask(agg text, kind text, val text)\nRETURNS text LANGUAGE sql STABLE AS $$\n SELECT CASE\n WHEN val IS NULL THEN NULL\n WHEN (agg || '.' || kind) = ANY (string_to_array(coalesce(current_setting('app.unmask', true), ''), ','))\n OR ('*.' || kind) = ANY (string_to_array(coalesce(current_setting('app.unmask', true), ''), ',')) THEN val\n WHEN kind = 'phone' THEN CASE WHEN length(val) >= 7 THEN left(val, 3) || '****' || right(val, 4) ELSE '****' END\n WHEN kind = 'idCard' THEN CASE WHEN length(val) >= 8 THEN left(val, 4) || '**********' || right(val, 4) ELSE '****' END\n WHEN kind = 'bankCard' THEN '**** **** **** ' || right(val, 4)\n WHEN kind = 'email' THEN CASE WHEN strpos(val, '@') > 1 THEN left(val, 1) || '***' || substr(val, strpos(val, '@')) ELSE '******' END\n WHEN kind = 'name' THEN left(val, 1) || '**'\n WHEN kind = 'address' THEN left(val, 6) || '******'\n ELSE '******'\n END\n$$;";
|
|
70
|
+
/**
|
|
71
|
+
* 为单聚合生成 RLS 和 security_barrier 安全视图;hidden/关系字段不投影,敏感字段调用 sys.mask。
|
|
72
|
+
* cage_read 只有视图 SELECT,视图属主受到范围策略;cage_app 的写入授权由内核流水线执行。
|
|
73
|
+
*/
|
|
44
74
|
export declare function aggregateSafeSql(agg: AnyAggregate): string;
|
|
75
|
+
/** 系统审计视图只做租户过滤,系统管理接口还需检查 Sys.audit.read 等能力。 */
|
|
45
76
|
export declare const SYSTEM_SAFE_SQL = "\n-- \u5BA1\u8BA1\u67E5\u8BE2\u89C6\u56FE\uFF1A\u8BFB\u4FA7\u8D26\u53F7\u7ECF\u7CFB\u7EDF\u7BA1\u7406\u63A5\u53E3\u4F7F\u7528\uFF0C\u6309\u79DF\u6237\u8FC7\u6EE4\nDROP VIEW IF EXISTS safe.audit_log;\nCREATE VIEW safe.audit_log WITH (security_barrier) AS\n SELECT id, at, actor, actor_kind, on_behalf_of, source, kind, capability, command, aggregate, aggregate_id,\n result, diff, request_id, idempotency_key, client\n FROM sys.audit_log\n WHERE tenant_id = nullif(current_setting('app.tenant_id', true), '')::uuid;\nALTER VIEW safe.audit_log OWNER TO cage_view_owner;\nGRANT SELECT ON safe.audit_log TO cage_read;";
|
|
46
77
|
/** 整个安全层:先删掉旧的 safe 视图,再按声明重建(幂等) */
|
|
78
|
+
/** 主视图先于关系视图重建;关系视图连接双方安全视图,因此来源/目标范围和逻辑删除都生效。 */
|
|
47
79
|
export declare function safeLayerSql(reg: Registry): string;
|
|
80
|
+
/** 初始化专用账号所需秘密;仅用于生成/执行受控初始化 SQL,不应写入源码、日志或公开文档。 */
|
|
48
81
|
export interface BootstrapPasswords {
|
|
49
82
|
app: string;
|
|
50
83
|
read: string;
|
|
51
84
|
migrate: string;
|
|
52
85
|
}
|
|
53
86
|
/** 建库时执行一次(超级用户):模式、账号、默认权限 */
|
|
87
|
+
/**
|
|
88
|
+
* 为已有数据库生成模式、角色与默认权限 SQL;函数本身不执行、不建库,也不提供业务数据初始化。
|
|
89
|
+
* SQL 含密码且会调整既有同名账号,调用方必须先核对集群角色复用策略,不能直接用于普通 dev 启动。
|
|
90
|
+
*/
|
|
54
91
|
export declare function bootstrapSql(pw: BootstrapPasswords, dbName?: string): string;
|
|
55
92
|
/** 单租户部署使用的默认租户(启用多租户时每个租户一行 sys.tenant) */
|
|
56
93
|
export declare const DEFAULT_TENANT = "00000000-0000-4000-8000-000000000001";
|
|
57
94
|
/** 框架系统表(框架自己的迁移流,按名字记入 sys.schema_migrations) */
|
|
95
|
+
/** 系统迁移按数组顺序前向执行;历史 SQL(包括字符串内注释)参与 checksum,必须保持不可变。 */
|
|
58
96
|
export declare const SYSTEM_MIGRATIONS: {
|
|
59
97
|
name: string;
|
|
60
98
|
sql: string;
|
|
61
99
|
}[];
|
|
100
|
+
/** 迁移账本记录名称、摘要及提交时间;执行器先建账本,再校验全部已执行文件内容。 */
|
|
62
101
|
export declare const SCHEMA_MIGRATIONS_SQL = "\nCREATE TABLE IF NOT EXISTS sys.schema_migrations (\n name text PRIMARY KEY,\n checksum text,\n applied_at timestamptz NOT NULL DEFAULT now()\n);";
|