@yss123/cage-connectors 0.0.0-stage → 0.2.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 shunshunyue and Cage contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,19 @@
1
- # Temporary Holding Version
1
+ # @yss123/cage-connectors
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ 第三方连接器原语与运行时
4
+
5
+ Cage 是通过 TypeScript 声明业务、由框架统一执行权限和数据规则的中后台框架。此包是框架的一部分。
6
+
7
+ ## 使用
8
+
9
+ ```powershell
10
+ pnpm add @yss123/cage-connectors
11
+ ```
12
+
13
+ 首次使用建议通过脚手架创建完整项目,所需依赖由模板统一配置。需要 Node.js 24 或更新版本。
14
+
15
+ - [完整使用说明](https://github.com/shunshunyue/cage/blob/main/docs/使用说明.md)
16
+ - [框架源码与范例](https://github.com/shunshunyue/cage)
17
+ - [问题反馈](https://github.com/shunshunyue/cage/issues)
18
+
19
+ 许可证:[MIT](https://github.com/shunshunyue/cage/blob/main/LICENSE)。
@@ -0,0 +1,2 @@
1
+ export { connector, op, outbound, inbound, hmacSha256, type Connector, type ConnectorDef, type Op, type OpDef, type Effect, type Outbound, type Inbound, type Verifier, } from './primitives.js';
2
+ export { call, stage, secrets, setSecretProvider, fakeConnector, fakeCalls, sampleFromSchema, outboundConsumer, ConnectorError, type SecretProvider, } from './runtime.js';
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ // @yss123/cage-connectors:第三方连接器原语与运行时。
2
+ export { connector, op, outbound, inbound, hmacSha256, } from './primitives.js';
3
+ export { call, stage, secrets, setSecretProvider, fakeConnector, fakeCalls, sampleFromSchema, outboundConsumer, ConnectorError, } from './runtime.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,wCAAwC;AACxC,OAAO,EACL,SAAS,EAAE,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,GAE7C,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,SAAS,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,cAAc,GAEtH,MAAM,cAAc,CAAC"}
@@ -0,0 +1,107 @@
1
+ import { CONNECTOR, CONSUMERS, INBOUND, OUTBOUND, type AnyCommand, type AnyEvent, type Kernel, type PayloadOf } from '@yss123/cage-kernel';
2
+ import type { EventConsumer } from '@yss123/cage-kernel/worker';
3
+ import { z } from 'zod';
4
+ /** 副作用等级:read 只读;retryableWrite 可重试写(对方按幂等键去重);write 不可重试写(失败直接进死信,人工处理) */
5
+ export type Effect = 'read' | 'retryableWrite' | 'write';
6
+ export interface OpDef<Req extends z.ZodObject<any> = z.ZodObject<any>, Res extends z.ZodType = z.ZodType> {
7
+ effect: Effect;
8
+ method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
9
+ path: string;
10
+ /** 出站字段白名单:只允许发这些字段 */
11
+ request: Req;
12
+ /** 对方返回的格式:响应也按声明校验,对方格式变了立即发现 */
13
+ response: Res;
14
+ }
15
+ export interface Op<Req extends z.ZodObject<any> = z.ZodObject<any>, Res extends z.ZodType = z.ZodType> extends OpDef<Req, Res> {
16
+ readonly name: string;
17
+ readonly connector: Connector;
18
+ }
19
+ export declare function op<Req extends z.ZodObject<any>, Res extends z.ZodType>(def: OpDef<Req, Res>): OpDef<Req, Res>;
20
+ export interface ConnectorDef<Ops extends Record<string, OpDef<any, any>>> {
21
+ /** 地址白名单:按环境各一个,代码里写不了任意地址 */
22
+ hosts: {
23
+ test?: string;
24
+ prod?: string;
25
+ [stage: string]: string | undefined;
26
+ };
27
+ /** 只写密钥名,值由密钥管理服务(或环境变量)注入 */
28
+ secret?: string;
29
+ timeoutMs?: number;
30
+ retry?: {
31
+ max: number;
32
+ backoff: 'exponential' | 'fixed';
33
+ };
34
+ rateLimit?: {
35
+ perSecond: number;
36
+ };
37
+ operations: Ops;
38
+ }
39
+ export interface Connector<Ops extends Record<string, OpDef<any, any>> = Record<string, OpDef<any, any>>> {
40
+ readonly [CONNECTOR]: true;
41
+ readonly name: string;
42
+ readonly hosts: ConnectorDef<Ops>['hosts'];
43
+ readonly secret?: string;
44
+ readonly timeoutMs: number;
45
+ readonly retry: {
46
+ max: number;
47
+ backoff: 'exponential' | 'fixed';
48
+ };
49
+ readonly rateLimit?: {
50
+ perSecond: number;
51
+ };
52
+ readonly operations: {
53
+ readonly [K in keyof Ops]: Op<Ops[K]['request'], Ops[K]['response']>;
54
+ };
55
+ }
56
+ export declare function connector<Ops extends Record<string, OpDef<any, any>>>(name: string, def: ConnectorDef<Ops>): Connector<Ops>;
57
+ export interface Outbound<E extends AnyEvent = AnyEvent, O extends Op = Op> {
58
+ readonly [OUTBOUND]: true;
59
+ readonly event: E;
60
+ readonly op: O;
61
+ readonly idempotencyKey: (e: PayloadOf<E>) => string;
62
+ /** 出站映射:我们的事件转成对方请求(纯函数);返回 null 表示这次不推 */
63
+ readonly map: (e: PayloadOf<E>) => z.input<O['request']> | null;
64
+ /** 成功后怎么回写:通过命令回写,而不是直接改表 */
65
+ readonly onSuccess?: {
66
+ command: AnyCommand;
67
+ map: (res: z.output<O['response']>, e: PayloadOf<E>) => unknown;
68
+ };
69
+ /** 映射用到的事件字段,进入本体图 */
70
+ readonly fields?: readonly string[];
71
+ readonly [CONSUMERS]: (k: Kernel) => EventConsumer[];
72
+ }
73
+ export declare function outbound<E extends AnyEvent, O extends Op>(ev: E, operation: O, def: {
74
+ idempotencyKey: (e: PayloadOf<E>) => string;
75
+ map: (e: PayloadOf<E>) => z.input<O['request']> | null;
76
+ onSuccess?: {
77
+ command: AnyCommand;
78
+ map: (res: z.output<O['response']>, e: PayloadOf<E>) => unknown;
79
+ };
80
+ fields?: string[];
81
+ }): Outbound<E, O>;
82
+ export interface Verifier {
83
+ readonly kind: string;
84
+ readonly secret: string;
85
+ verify(rawBody: string, headers: Record<string, string | string[] | undefined>, secretValue: string): boolean;
86
+ }
87
+ /** HMAC-SHA256 验签:签名放在请求头(默认 x-signature),值为 hex 或 sha256=hex */
88
+ export declare function hmacSha256(secret: string, opts?: {
89
+ header?: string;
90
+ }): Verifier;
91
+ export interface Inbound<P extends z.ZodType = z.ZodType> {
92
+ readonly [INBOUND]: true;
93
+ readonly connector: Connector<any>;
94
+ /** 事件名,生成路由 POST /hooks/{connector}/{event-kebab} */
95
+ readonly event: string;
96
+ readonly verify: Verifier;
97
+ readonly payload: P;
98
+ /** 映射到的命令,以 external 身份调用 */
99
+ readonly command: AnyCommand;
100
+ readonly map: (p: z.output<P>) => unknown;
101
+ }
102
+ export declare function inbound<P extends z.ZodType>(conn: Connector<any>, eventName: string, def: {
103
+ verify: Verifier;
104
+ payload: P;
105
+ command: AnyCommand;
106
+ map: (p: z.output<P>) => unknown;
107
+ }): Inbound<P>;
@@ -0,0 +1,67 @@
1
+ // 连接器原语:声明对方系统的地址白名单、密钥名、操作清单和调用策略;AI 只写两头的映射函数。
2
+ import { createHmac, timingSafeEqual } from 'node:crypto';
3
+ import { CONNECTOR, CONSUMERS, INBOUND, OUTBOUND, declError, } from '@yss123/cage-kernel';
4
+ import { outboundConsumer } from './runtime.js';
5
+ export function op(def) {
6
+ if (!def.path.startsWith('/'))
7
+ throw declError('CAGE-CONN-002', `操作路径 ${def.path} 必须以 / 开头`);
8
+ return def;
9
+ }
10
+ export function connector(name, def) {
11
+ if (!/^[a-z][a-z0-9-]*$/.test(name))
12
+ throw declError('CAGE-CONN-001', `连接器名 ${name} 必须是小写短横线`);
13
+ for (const h of Object.values(def.hosts)) {
14
+ if (h && /[/:\s]/.test(h.replace(/:\d+$/, '')))
15
+ throw declError('CAGE-CONN-003', `地址白名单只能写主机名(可带端口):${h}`);
16
+ }
17
+ const c = {
18
+ [CONNECTOR]: true,
19
+ name,
20
+ hosts: Object.freeze({ ...def.hosts }),
21
+ secret: def.secret,
22
+ timeoutMs: def.timeoutMs ?? 5000,
23
+ retry: def.retry ?? { max: 5, backoff: 'exponential' },
24
+ rateLimit: def.rateLimit,
25
+ };
26
+ c.operations = Object.freeze(Object.fromEntries(Object.entries(def.operations).map(([k, o]) => [k, Object.freeze({ ...o, name: k, connector: c })])));
27
+ return Object.freeze(c);
28
+ }
29
+ export function outbound(ev, operation, def) {
30
+ if (operation.effect === 'read')
31
+ throw declError('CAGE-CONN-004', '只读操作不能用于出站映射');
32
+ const o = {
33
+ [OUTBOUND]: true,
34
+ event: ev,
35
+ op: operation,
36
+ idempotencyKey: def.idempotencyKey,
37
+ map: def.map,
38
+ onSuccess: def.onSuccess,
39
+ fields: def.fields ?? Object.keys(ev.fields),
40
+ };
41
+ o[CONSUMERS] = (k) => [outboundConsumer(k, o)];
42
+ return Object.freeze(o);
43
+ }
44
+ /** HMAC-SHA256 验签:签名放在请求头(默认 x-signature),值为 hex 或 sha256=hex */
45
+ export function hmacSha256(secret, opts = {}) {
46
+ const header = (opts.header ?? 'x-signature').toLowerCase();
47
+ return Object.freeze({
48
+ kind: 'hmac-sha256',
49
+ secret,
50
+ verify(rawBody, headers, secretValue) {
51
+ const got = String(headers[header] ?? '').replace(/^sha256=/, '');
52
+ if (!/^[0-9a-f]{64}$/i.test(got))
53
+ return false;
54
+ const want = createHmac('sha256', secretValue).update(rawBody).digest('hex');
55
+ return timingSafeEqual(Buffer.from(got, 'hex'), Buffer.from(want, 'hex'));
56
+ },
57
+ });
58
+ }
59
+ export function inbound(conn, eventName, def) {
60
+ if (!/^[a-z][A-Za-z0-9]*$/.test(eventName))
61
+ throw declError('CAGE-CONN-005', `入站事件名 ${eventName} 必须是小驼峰`);
62
+ if (!def.command.invokedBy.includes('external') && !def.command.invokedBy.includes('user')) {
63
+ throw declError('CAGE-CONN-006', `入站回调调用的命令必须声明 invokedBy: 'external'`);
64
+ }
65
+ return Object.freeze({ [INBOUND]: true, connector: conn, event: eventName, ...def });
66
+ }
67
+ //# sourceMappingURL=primitives.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"primitives.js","sourceRoot":"","sources":["../src/primitives.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ import { type Kernel } from '@yss123/cage-kernel';
2
+ import type { EventConsumer } from '@yss123/cage-kernel/worker';
3
+ import { z } from 'zod';
4
+ import type { Connector, Op, Outbound } from './primitives.js';
5
+ /** 运行阶段:fake(本地与 CI,不访问网络)、test(第三方沙箱)、prod */
6
+ export declare function stage(): string;
7
+ export interface SecretProvider {
8
+ get(name: string): Promise<string>;
9
+ }
10
+ export declare function setSecretProvider(p: SecretProvider): void;
11
+ export declare const secrets: {
12
+ get: (name: string) => Promise<string>;
13
+ };
14
+ export declare function take(c: Connector<any>): Promise<void>;
15
+ type FakeHandler = (req: any) => unknown | Promise<unknown>;
16
+ export declare const fakeCalls: {
17
+ connector: string;
18
+ operation: string;
19
+ request: unknown;
20
+ key: string;
21
+ }[];
22
+ /** 注册 fake 实现:fakeConnector(erp, { pushOrder: (req) => ({ erpNo: 'FAKE-' + req.externalId }) }) */
23
+ export declare function fakeConnector(c: Connector<any>, handlers: Record<string, FakeHandler>): void;
24
+ /** 没有注册 fake 时按响应 schema 造一个示例值 */
25
+ export declare function sampleFromSchema(schema: z.ZodType, seed?: string): unknown;
26
+ export declare class ConnectorError extends Error {
27
+ readonly status: number | null;
28
+ readonly retryable: boolean;
29
+ constructor(message: string, status: number | null, retryable: boolean);
30
+ }
31
+ /** 调用一个连接器操作。白名单外的字段直接报错,不会被悄悄发出去。 */
32
+ export declare function call(o: Op, payload: unknown, key: string, opts?: {
33
+ kernel?: Kernel;
34
+ tenantId?: string;
35
+ }): Promise<any>;
36
+ /** 出站映射的事件消费者:调用第三方,成功后以 external 身份执行回写命令,和去重登记同一个事务 */
37
+ export declare function outboundConsumer(k: Kernel, ob: Outbound): EventConsumer;
38
+ export {};
@@ -0,0 +1,195 @@
1
+ // 连接器运行时:每一道管控都在这里发生——字段白名单、地址白名单、密钥、限流、超时、调用记录、响应校验。
2
+ import { systemCtx } from '@yss123/cage-kernel';
3
+ import { sql } from 'kysely';
4
+ import { z } from 'zod';
5
+ /** 运行阶段:fake(本地与 CI,不访问网络)、test(第三方沙箱)、prod */
6
+ export function stage() {
7
+ return process.env.CAGE_STAGE ?? (process.env.NODE_ENV === 'production' ? 'prod' : 'fake');
8
+ }
9
+ let secretProvider = {
10
+ async get(name) {
11
+ const v = process.env[name];
12
+ if (!v)
13
+ throw new Error(`[CAGE-SECRET-001] 缺少密钥 ${name}(由密钥管理服务或环境变量注入)`);
14
+ return v;
15
+ },
16
+ };
17
+ export function setSecretProvider(p) {
18
+ secretProvider = p;
19
+ }
20
+ export const secrets = { get: (name) => secretProvider.get(name) };
21
+ // ---------------- 限流 ----------------
22
+ const buckets = new Map();
23
+ export async function take(c) {
24
+ const rate = c.rateLimit?.perSecond;
25
+ if (!rate)
26
+ return;
27
+ for (;;) {
28
+ const now = Date.now();
29
+ const b = buckets.get(c.name) ?? { tokens: rate, at: now };
30
+ b.tokens = Math.min(rate, b.tokens + ((now - b.at) / 1000) * rate);
31
+ b.at = now;
32
+ if (b.tokens >= 1) {
33
+ b.tokens -= 1;
34
+ buckets.set(c.name, b);
35
+ return;
36
+ }
37
+ buckets.set(c.name, b);
38
+ await new Promise((r) => setTimeout(r, Math.ceil(((1 - b.tokens) / rate) * 1000)));
39
+ }
40
+ }
41
+ const fakes = new Map();
42
+ export const fakeCalls = [];
43
+ /** 注册 fake 实现:fakeConnector(erp, { pushOrder: (req) => ({ erpNo: 'FAKE-' + req.externalId }) }) */
44
+ export function fakeConnector(c, handlers) {
45
+ for (const [op, h] of Object.entries(handlers))
46
+ fakes.set(`${c.name}.${op}`, h);
47
+ }
48
+ /** 没有注册 fake 时按响应 schema 造一个示例值 */
49
+ export function sampleFromSchema(schema, seed = 'fake') {
50
+ const js = z.toJSONSchema(schema, { unrepresentable: 'any' });
51
+ const gen = (s) => {
52
+ if (!s)
53
+ return null;
54
+ if (s.const !== undefined)
55
+ return s.const;
56
+ if (s.enum)
57
+ return s.enum[0];
58
+ if (s.anyOf)
59
+ return gen(s.anyOf[0]);
60
+ switch (s.type) {
61
+ case 'object':
62
+ return Object.fromEntries(Object.entries(s.properties ?? {}).map(([k, v]) => [k, gen(v)]));
63
+ case 'array':
64
+ return [];
65
+ case 'string':
66
+ return s.format === 'uuid' ? '00000000-0000-4000-8000-000000000000' : `${seed.toUpperCase()}-${Date.now().toString(36)}`;
67
+ case 'integer':
68
+ case 'number':
69
+ return 0;
70
+ case 'boolean':
71
+ return false;
72
+ default:
73
+ return null;
74
+ }
75
+ };
76
+ return gen(js);
77
+ }
78
+ // ---------------- 调用 ----------------
79
+ export class ConnectorError extends Error {
80
+ status;
81
+ retryable;
82
+ constructor(message, status, retryable) {
83
+ super(message);
84
+ this.status = status;
85
+ this.retryable = retryable;
86
+ this.name = 'ConnectorError';
87
+ }
88
+ }
89
+ async function recordCall(k, o, key, tenantId, status, httpStatus, request, response, error) {
90
+ if (!k)
91
+ return;
92
+ await k.app
93
+ .insertInto('sys.sync_record')
94
+ .values({
95
+ tenant_id: tenantId, connector: o.connector.name, operation: o.name, idempotency_key: key, ref_id: key, status,
96
+ http_status: httpStatus, request: JSON.stringify(request), response: response === undefined ? null : JSON.stringify(response), error: error ?? null,
97
+ })
98
+ .onConflict((oc) => oc.columns(['connector', 'operation', 'idempotency_key']).doUpdateSet({
99
+ status, http_status: httpStatus, attempts: sql `sys.sync_record.attempts + 1`, response: response === undefined ? null : JSON.stringify(response),
100
+ error: error ?? null, updated_at: sql `now()`,
101
+ }))
102
+ .execute()
103
+ .catch((e) => k.log.warn({ err: String(e) }, '同步记录写入失败'));
104
+ }
105
+ /** 调用一个连接器操作。白名单外的字段直接报错,不会被悄悄发出去。 */
106
+ export async function call(o, payload, key, opts = {}) {
107
+ const body = o.request.strict().parse(payload);
108
+ const st = stage();
109
+ if (st === 'fake') {
110
+ const h = fakes.get(`${o.connector.name}.${o.name}`);
111
+ const res = h ? await h(body) : sampleFromSchema(o.response, o.connector.name);
112
+ fakeCalls.push({ connector: o.connector.name, operation: o.name, request: body, key });
113
+ const parsed = o.response.parse(res);
114
+ await recordCall(opts.kernel, o, key, opts.tenantId ?? null, 'ok', 200, body, parsed);
115
+ return parsed;
116
+ }
117
+ const host = o.connector.hosts[st];
118
+ if (!host)
119
+ throw new ConnectorError(`[CAGE-CONN-007] 连接器 ${o.connector.name} 没有 ${st} 环境的地址`, null, false);
120
+ const token = o.connector.secret ? await secrets.get(o.connector.secret) : undefined;
121
+ await take(o.connector);
122
+ const url = new URL(o.path, `https://${host}`);
123
+ if (o.method === 'GET')
124
+ for (const [k, v] of Object.entries(body))
125
+ url.searchParams.set(k, String(v));
126
+ let res;
127
+ try {
128
+ // 生产环境出站流量经过出口代理:设置 HTTPS_PROXY 与 NODE_USE_ENV_PROXY=1
129
+ res = await fetch(url, {
130
+ method: o.method,
131
+ headers: {
132
+ 'content-type': 'application/json',
133
+ ...(token ? { authorization: `Bearer ${token}` } : {}),
134
+ 'idempotency-key': key,
135
+ },
136
+ body: o.method === 'GET' ? undefined : JSON.stringify(body),
137
+ signal: AbortSignal.timeout(o.connector.timeoutMs),
138
+ });
139
+ }
140
+ catch (e) {
141
+ await recordCall(opts.kernel, o, key, opts.tenantId ?? null, 'failed', null, body, undefined, String(e));
142
+ throw new ConnectorError(`[CAGE-CONN-008] 调用 ${o.connector.name}.${o.name} 失败:${String(e)}`, null, true);
143
+ }
144
+ const text = await res.text();
145
+ let json = null;
146
+ try {
147
+ json = text ? JSON.parse(text) : null;
148
+ }
149
+ catch {
150
+ json = { raw: text.slice(0, 500) };
151
+ }
152
+ if (!res.ok) {
153
+ await recordCall(opts.kernel, o, key, opts.tenantId ?? null, 'failed', res.status, body, json);
154
+ const retryable = o.effect === 'retryableWrite' || o.effect === 'read' ? res.status >= 500 || res.status === 429 : false;
155
+ throw new ConnectorError(`[CAGE-CONN-009] ${o.connector.name}.${o.name} 返回 ${res.status}`, res.status, retryable);
156
+ }
157
+ const parsed = o.response.safeParse(json);
158
+ if (!parsed.success) {
159
+ await recordCall(opts.kernel, o, key, opts.tenantId ?? null, 'failed', res.status, body, json, '响应格式不符合声明');
160
+ throw new ConnectorError(`[CAGE-CONN-010] ${o.connector.name}.${o.name} 的响应格式与声明不符`, res.status, false);
161
+ }
162
+ await recordCall(opts.kernel, o, key, opts.tenantId ?? null, 'ok', res.status, body, parsed.data);
163
+ return parsed.data;
164
+ }
165
+ /** 出站映射的事件消费者:调用第三方,成功后以 external 身份执行回写命令,和去重登记同一个事务 */
166
+ export function outboundConsumer(k, ob) {
167
+ const name = `outbound:${ob.op.connector.name}.${ob.op.name}:${ob.event.name}`;
168
+ return {
169
+ name,
170
+ event: ob.event.name,
171
+ async handle(row, tx) {
172
+ const req = ob.map(row.payload);
173
+ if (req === null || req === undefined)
174
+ return;
175
+ const key = ob.idempotencyKey(row.payload);
176
+ let res;
177
+ try {
178
+ res = await call(ob.op, req, key, { kernel: k, tenantId: row.tenant_id });
179
+ }
180
+ catch (e) {
181
+ if (e instanceof ConnectorError && !e.retryable) {
182
+ // 不可重试:标成永久错误,直接进死信
183
+ throw Object.assign(new Error(`[CAGE-CONN-011] ${e.message}`), { permanent: true });
184
+ }
185
+ throw e;
186
+ }
187
+ if (ob.onSuccess) {
188
+ const input = ob.onSuccess.map(res, row.payload);
189
+ const ctx = systemCtx({ kind: 'external', name: ob.op.connector.name, tenantId: row.tenant_id, capabilities: [k.registry.capabilityOf(ob.onSuccess.command)], requestId: row.request_id ?? undefined });
190
+ await k.executeIn(tx, ob.onSuccess.command, input, ctx, 0);
191
+ }
192
+ },
193
+ };
194
+ }
195
+ //# sourceMappingURL=runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,43 @@
1
1
  {
2
2
  "name": "@yss123/cage-connectors",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.2.0",
4
+ "description": "第三方连接器原语与运行时",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "default": "./dist/index.js"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist"
16
+ ],
17
+ "dependencies": {
18
+ "zod": "^4.1.5",
19
+ "kysely": "^0.28.5",
20
+ "@yss123/cage-kernel": "0.2.0"
21
+ },
22
+ "license": "MIT",
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "git+https://github.com/shunshunyue/cage.git",
26
+ "directory": "packages/connectors"
27
+ },
28
+ "homepage": "https://github.com/shunshunyue/cage#readme",
29
+ "bugs": {
30
+ "url": "https://github.com/shunshunyue/cage/issues"
31
+ },
32
+ "publishConfig": {
33
+ "access": "public",
34
+ "registry": "https://registry.npmjs.org/"
35
+ },
36
+ "engines": {
37
+ "node": ">=24"
38
+ },
39
+ "scripts": {
40
+ "build": "tsc -p tsconfig.json",
41
+ "typecheck": "tsc -p tsconfig.json --noEmit"
42
+ }
6
43
  }