@deepexi/datasense-connector 3.0.1 → 3.1.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 +158 -139
- package/package.json +19 -28
- package/scripts/build.ts +188 -0
- package/src/define.ts +267 -0
- package/src/descriptor.ts +116 -0
- package/src/errors.ts +105 -0
- package/src/index.ts +108 -0
- package/src/internal/location.ts +23 -0
- package/src/runtime/guest/bridge.ts +238 -0
- package/src/runtime/guest/cache.ts +43 -0
- package/src/runtime/guest/check.ts +17 -0
- package/src/runtime/guest/crypto.ts +166 -0
- package/src/runtime/guest/ctx.ts +157 -0
- package/src/runtime/guest/db.ts +59 -0
- package/src/runtime/guest/failure.ts +69 -0
- package/src/runtime/guest/http.ts +194 -0
- package/src/runtime/guest/index.ts +102 -0
- package/{runtime/guest/limits.d.ts → src/runtime/guest/limits.ts} +12 -12
- package/src/runtime/guest/loader.ts +210 -0
- package/src/runtime/guest/log.ts +47 -0
- package/src/runtime/guest/map.ts +45 -0
- package/src/runtime/guest/operation.ts +193 -0
- package/src/runtime/guest/paginate.ts +169 -0
- package/src/runtime/guest/pull.ts +177 -0
- package/src/runtime/guest/push.ts +92 -0
- package/src/runtime/guest/signal.ts +14 -0
- package/src/runtime/guest/suggest.ts +51 -0
- package/src/runtime/guest/time.ts +137 -0
- package/src/runtime/guest-runtime.ts +75 -0
- package/src/runtime/index.ts +53 -0
- package/src/runtime/protocol.ts +557 -0
- package/src/runtime/session.ts +216 -0
- package/src/testing/child.ts +21 -0
- package/src/testing/compliance.ts +343 -0
- package/src/testing/engine.ts +445 -0
- package/src/testing/fixtures.ts +591 -0
- package/src/testing/gateway.ts +482 -0
- package/src/testing/import-guard.ts +221 -0
- package/src/testing/index.ts +43 -0
- package/src/testing/local-db.ts +226 -0
- package/src/testing/mock-external-system.ts +249 -0
- package/src/testing/pinned-http.ts +144 -0
- package/src/testing/recorder.ts +140 -0
- package/src/testing/redaction.ts +94 -0
- package/src/testing/replay.ts +437 -0
- package/src/testing/run-tests.ts +115 -0
- package/src/testing/schema.ts +70 -0
- package/src/testing/source-loader.ts +374 -0
- package/src/testing/types.ts +78 -0
- package/src/types.ts +329 -0
- package/src/validate.ts +267 -0
- package/test/build.test.ts +159 -0
- package/test/define.test-d.ts +182 -0
- package/test/fixtures/acceptance.ts +156 -0
- package/test/fixtures/connectors/http-pull/.ontos/descriptor.json +72 -0
- package/test/fixtures/connectors/http-pull/.ontos/types.ts +61 -0
- package/test/fixtures/connectors/http-pull/package.json +5 -0
- package/test/fixtures/connectors/http-pull/streams/items/index.ts +37 -0
- package/test/fixtures/connectors/http-pull/streams/items/map.ts +12 -0
- package/test/fixtures/connectors/http-pull/streams/items/tests/basic/case.json +15 -0
- package/test/fixtures/connectors/http-pull/streams/items/tests/basic/exchanges.ndjson +2 -0
- package/test/fixtures/connectors/pg-pull/.ontos/descriptor.json +151 -0
- package/test/fixtures/connectors/pg-pull/.ontos/types.ts +62 -0
- package/test/fixtures/connectors/pg-pull/lib/sql.ts +14 -0
- package/test/fixtures/connectors/pg-pull/package.json +5 -0
- package/test/fixtures/connectors/pg-pull/streams/customers/index.ts +30 -0
- package/test/fixtures/connectors/pg-pull/streams/customers/tests/customers-full/case.json +15 -0
- package/test/fixtures/connectors/pg-pull/streams/customers/tests/customers-full/exchanges.ndjson +3 -0
- package/test/fixtures/connectors/pg-pull/streams/orders/index.ts +32 -0
- package/test/fixtures/descriptor.ts +54 -0
- package/test/fixtures/kingdee-example.ts +82 -0
- package/test/fixtures/record-acceptance.ts +32 -0
- package/test/runtime/ctx.test.ts +434 -0
- package/test/runtime/helpers.ts +157 -0
- package/test/runtime/jobs.test.ts +444 -0
- package/test/runtime/operation.test.ts +175 -0
- package/test/runtime/session.test.ts +229 -0
- package/test/testing/acceptance-fixtures.test.ts +69 -0
- package/test/testing/compliance.test.ts +247 -0
- package/test/testing/engine.test.ts +283 -0
- package/test/testing/fixtures.test.ts +221 -0
- package/test/testing/gateway.test.ts +337 -0
- package/test/testing/import-guard.test.ts +45 -0
- package/test/testing/mock-external-system.test.ts +144 -0
- package/test/testing/operation-fixtures.test.ts +160 -0
- package/test/testing/recorder.test.ts +163 -0
- package/test/testing/redaction.test.ts +54 -0
- package/test/testing/replay.test.ts +207 -0
- package/test/testing/run-tests.test.ts +137 -0
- package/test/testing/source-loader.test.ts +220 -0
- package/test/validate-config.test.ts +104 -0
- package/tsconfig.build.json +23 -0
- package/tsconfig.json +19 -0
- package/cjs/index.cjs +0 -1015
- package/cjs/runtime.cjs +0 -752
- package/cjs/testing.cjs +0 -3591
- package/errors.d.ts +0 -17
- package/errors.js +0 -53
- package/guest.cjs +0 -2659
- package/index.d.ts +0 -13
- package/index.js +0 -7
- package/internal/location.d.ts +0 -6
- package/internal/location.js +0 -8
- package/presentation.d.ts +0 -38
- package/presentation.js +0 -268
- package/runtime/guest/bridge.d.ts +0 -53
- package/runtime/guest/bridge.js +0 -187
- package/runtime/guest/cache.d.ts +0 -3
- package/runtime/guest/cache.js +0 -42
- package/runtime/guest/crypto.d.ts +0 -13
- package/runtime/guest/crypto.js +0 -177
- package/runtime/guest/ctx.d.ts +0 -30
- package/runtime/guest/ctx.js +0 -124
- package/runtime/guest/db.d.ts +0 -6
- package/runtime/guest/db.js +0 -59
- package/runtime/guest/discover.d.ts +0 -29
- package/runtime/guest/discover.js +0 -51
- package/runtime/guest/failure.d.ts +0 -24
- package/runtime/guest/failure.js +0 -63
- package/runtime/guest/http.d.ts +0 -4
- package/runtime/guest/http.js +0 -204
- package/runtime/guest/index.d.ts +0 -12
- package/runtime/guest/index.js +0 -89
- package/runtime/guest/limits.js +0 -12
- package/runtime/guest/loader.d.ts +0 -15
- package/runtime/guest/loader.js +0 -42
- package/runtime/guest/log.d.ts +0 -10
- package/runtime/guest/log.js +0 -36
- package/runtime/guest/map.d.ts +0 -4
- package/runtime/guest/map.js +0 -45
- package/runtime/guest/paginate.d.ts +0 -6
- package/runtime/guest/paginate.js +0 -180
- package/runtime/guest/pull.d.ts +0 -12
- package/runtime/guest/pull.js +0 -150
- package/runtime/guest/push.d.ts +0 -18
- package/runtime/guest/push.js +0 -80
- package/runtime/guest/signal.d.ts +0 -3
- package/runtime/guest/signal.js +0 -12
- package/runtime/guest/time.d.ts +0 -5
- package/runtime/guest/time.js +0 -127
- package/runtime/guest-runtime.d.ts +0 -7
- package/runtime/guest-runtime.js +0 -51
- package/runtime/index.d.ts +0 -18
- package/runtime/index.js +0 -3
- package/runtime/protocol.d.ts +0 -276
- package/runtime/protocol.js +0 -409
- package/runtime/session.d.ts +0 -12
- package/runtime/session.js +0 -191
- package/t.d.ts +0 -18
- package/t.js +0 -26
- package/testing/child.cjs +0 -350
- package/testing/child.d.ts +0 -1
- package/testing/child.js +0 -12
- package/testing/compliance.d.ts +0 -41
- package/testing/compliance.js +0 -291
- package/testing/engine.d.ts +0 -66
- package/testing/engine.js +0 -339
- package/testing/fixtures.d.ts +0 -145
- package/testing/fixtures.js +0 -407
- package/testing/gateway.d.ts +0 -65
- package/testing/gateway.js +0 -402
- package/testing/import-guard.d.ts +0 -57
- package/testing/import-guard.js +0 -187
- package/testing/index.d.ts +0 -33
- package/testing/index.js +0 -10
- package/testing/local-db.d.ts +0 -27
- package/testing/local-db.js +0 -181
- package/testing/pinned-http.d.ts +0 -14
- package/testing/pinned-http.js +0 -125
- package/testing/recorder.d.ts +0 -15
- package/testing/recorder.js +0 -116
- package/testing/redaction.d.ts +0 -28
- package/testing/redaction.js +0 -67
- package/testing/replay.d.ts +0 -50
- package/testing/replay.js +0 -313
- package/testing/schema.d.ts +0 -13
- package/testing/schema.js +0 -65
- package/testing/source-loader.d.ts +0 -19
- package/testing/source-loader.js +0 -238
- package/testing/types.d.ts +0 -79
- package/testing/types.js +0 -18
- package/types.d.ts +0 -302
- package/types.js +0 -13
- package/validate.d.ts +0 -78
- package/validate.js +0 -597
package/runtime/protocol.d.ts
DELETED
|
@@ -1,276 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* guest 运行时与宿主(runner 执行子进程 / 父进程)之间的消息契约。
|
|
3
|
-
*
|
|
4
|
-
* 消息只用 JSON 兼容结构。子进程起来后发 `ready`,父进程回一条 `execute`;之后子进程按需发 `call`
|
|
5
|
-
* (宿主调用),父进程逐条回 `reply`;最后子进程发 `result` 或 `failure`。父进程随时可以发 `cancel`。
|
|
6
|
-
*
|
|
7
|
-
* 宿主调用的 payload 与 shared 的出站网关线协议(`EgressHttpRequest` 等)结构一致;SDK 不依赖 shared,
|
|
8
|
-
* 这里自己定义一份同形的类型。子进程里跑的是不可信代码,父进程用 `parseChildMessage` 逐字段重建消息,
|
|
9
|
-
* 不直接信任子进程产出的结构。
|
|
10
|
-
*/
|
|
11
|
-
import type { DefinitionSummary, NormalizedDiscoverResult } from '../validate.js';
|
|
12
|
-
export type { DefinitionSummary } from '../validate.js';
|
|
13
|
-
export type NormalizedDiscover = NormalizedDiscoverResult;
|
|
14
|
-
export type HostMethod = 'definition' | 'declaration' | 'http' | 'db.query' | 'db.next' | 'db.close' | 'crypto' | 'cache.get' | 'cache.set' | 'secret.reveal' | 'emit';
|
|
15
|
-
export declare const HOST_METHODS: readonly HostMethod[];
|
|
16
|
-
export interface GuestPushRequest {
|
|
17
|
-
requestId: string;
|
|
18
|
-
push: string;
|
|
19
|
-
receivedAt: string;
|
|
20
|
-
headers: Record<string, string>;
|
|
21
|
-
body: string;
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* 作业:
|
|
25
|
-
* - `check`:只跑连接器的 `check`(没有时直接成功),结果 `{ kind: 'check'; ok: true; logs }`;
|
|
26
|
-
* - `pull` 带 `discoverFirst: true` 时 `tables` 可为 `[]`:guest 先跑 check + discover、经宿主调用 `declaration` 上报声明,
|
|
27
|
-
* 再用声明里该数据流的表跑拉取(预览用)。
|
|
28
|
-
*/
|
|
29
|
-
export type GuestJob = {
|
|
30
|
-
kind: 'push';
|
|
31
|
-
config: Record<string, unknown>;
|
|
32
|
-
secretFields: string[];
|
|
33
|
-
requests: GuestPushRequest[];
|
|
34
|
-
} | {
|
|
35
|
-
kind: 'discover';
|
|
36
|
-
config: Record<string, unknown>;
|
|
37
|
-
secretFields: string[];
|
|
38
|
-
} | {
|
|
39
|
-
kind: 'check';
|
|
40
|
-
config: Record<string, unknown>;
|
|
41
|
-
secretFields: string[];
|
|
42
|
-
} | {
|
|
43
|
-
kind: 'pull';
|
|
44
|
-
config: Record<string, unknown>;
|
|
45
|
-
secretFields: string[];
|
|
46
|
-
stream: string;
|
|
47
|
-
mode: 'full' | 'incremental';
|
|
48
|
-
state: unknown;
|
|
49
|
-
streamConfig: Record<string, unknown>;
|
|
50
|
-
tables: string[];
|
|
51
|
-
discoverFirst?: boolean;
|
|
52
|
-
};
|
|
53
|
-
export interface HostCallError {
|
|
54
|
-
code: string;
|
|
55
|
-
message: string;
|
|
56
|
-
status?: number;
|
|
57
|
-
retryAfterMs?: number;
|
|
58
|
-
}
|
|
59
|
-
export type ParentMessage = {
|
|
60
|
-
type: 'execute';
|
|
61
|
-
guest: string;
|
|
62
|
-
code: string;
|
|
63
|
-
expect: {
|
|
64
|
-
name: string;
|
|
65
|
-
version: string;
|
|
66
|
-
};
|
|
67
|
-
job: GuestJob;
|
|
68
|
-
} | {
|
|
69
|
-
type: 'reply';
|
|
70
|
-
id: number;
|
|
71
|
-
ok: true;
|
|
72
|
-
value: unknown;
|
|
73
|
-
} | {
|
|
74
|
-
type: 'reply';
|
|
75
|
-
id: number;
|
|
76
|
-
ok: false;
|
|
77
|
-
error: HostCallError;
|
|
78
|
-
} | {
|
|
79
|
-
type: 'cancel';
|
|
80
|
-
};
|
|
81
|
-
export interface GuestLog {
|
|
82
|
-
at: string;
|
|
83
|
-
level: 'info' | 'warn' | 'error';
|
|
84
|
-
message: string;
|
|
85
|
-
requestId?: string;
|
|
86
|
-
}
|
|
87
|
-
/** 与 shared 的 `RunnerPushResult` 同形。 */
|
|
88
|
-
export interface GuestPushResult {
|
|
89
|
-
kind: 'push';
|
|
90
|
-
records: Array<{
|
|
91
|
-
requestId: string;
|
|
92
|
-
table: string;
|
|
93
|
-
row: Record<string, unknown>;
|
|
94
|
-
}>;
|
|
95
|
-
removals: Array<{
|
|
96
|
-
requestId: string;
|
|
97
|
-
table: string;
|
|
98
|
-
key: Record<string, unknown>;
|
|
99
|
-
}>;
|
|
100
|
-
rejected: Array<{
|
|
101
|
-
requestId: string;
|
|
102
|
-
code: string;
|
|
103
|
-
message: string;
|
|
104
|
-
}>;
|
|
105
|
-
logs: GuestLog[];
|
|
106
|
-
}
|
|
107
|
-
/** `pull` 的 `stopped: true`:某次 `emit` 的回复带 `{ stop: true }`,guest 触发 `ctx.signal` 后正常结束(不是 `CANCELED`)。 */
|
|
108
|
-
export type GuestResult = GuestPushResult | {
|
|
109
|
-
kind: 'discover';
|
|
110
|
-
summary: DefinitionSummary;
|
|
111
|
-
discover: NormalizedDiscover;
|
|
112
|
-
logs: GuestLog[];
|
|
113
|
-
} | {
|
|
114
|
-
kind: 'check';
|
|
115
|
-
ok: true;
|
|
116
|
-
logs: GuestLog[];
|
|
117
|
-
} | {
|
|
118
|
-
kind: 'pull';
|
|
119
|
-
emittedBatches: number;
|
|
120
|
-
stopped?: boolean;
|
|
121
|
-
logs: GuestLog[];
|
|
122
|
-
};
|
|
123
|
-
export type GuestFailureCode = 'CONNECTOR_LOAD_FAILED' | 'CONFIG_INVALID' | 'SCHEMA_ERROR' | 'FATAL_ERROR' | 'AUTH_ERROR' | 'TRANSIENT_ERROR' | 'PUSH_UNKNOWN' | 'CANCELED';
|
|
124
|
-
export declare const GUEST_FAILURE_CODES: readonly GuestFailureCode[];
|
|
125
|
-
export type ChildMessage = {
|
|
126
|
-
type: 'ready';
|
|
127
|
-
} | {
|
|
128
|
-
type: 'call';
|
|
129
|
-
id: number;
|
|
130
|
-
method: HostMethod;
|
|
131
|
-
payload: unknown;
|
|
132
|
-
} | {
|
|
133
|
-
type: 'result';
|
|
134
|
-
result: GuestResult;
|
|
135
|
-
} | {
|
|
136
|
-
type: 'failure';
|
|
137
|
-
code: GuestFailureCode;
|
|
138
|
-
message: string;
|
|
139
|
-
stack?: string;
|
|
140
|
-
logs: GuestLog[];
|
|
141
|
-
};
|
|
142
|
-
export interface EgressHttpRequest {
|
|
143
|
-
method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD';
|
|
144
|
-
url: string;
|
|
145
|
-
headers: Record<string, string>;
|
|
146
|
-
query: Record<string, string | string[]>;
|
|
147
|
-
body: string | null;
|
|
148
|
-
bodyEncoding: 'utf8' | 'base64';
|
|
149
|
-
timeoutMs?: number;
|
|
150
|
-
}
|
|
151
|
-
export interface EgressHttpResponse {
|
|
152
|
-
status: number;
|
|
153
|
-
url: string;
|
|
154
|
-
headers: Record<string, string>;
|
|
155
|
-
body: string;
|
|
156
|
-
bodyEncoding: 'utf8' | 'base64';
|
|
157
|
-
}
|
|
158
|
-
export interface DbQueryRequest {
|
|
159
|
-
sql: string;
|
|
160
|
-
params: unknown[];
|
|
161
|
-
}
|
|
162
|
-
export interface DbQueryResponse {
|
|
163
|
-
cursorId: string | null;
|
|
164
|
-
fields: Array<{
|
|
165
|
-
name: string;
|
|
166
|
-
dataTypeId: number;
|
|
167
|
-
}>;
|
|
168
|
-
rows: Array<Record<string, unknown>>;
|
|
169
|
-
done: boolean;
|
|
170
|
-
}
|
|
171
|
-
export interface DbCursorRequest {
|
|
172
|
-
cursorId: string;
|
|
173
|
-
}
|
|
174
|
-
export interface DbNextResponse {
|
|
175
|
-
rows: Array<Record<string, unknown>>;
|
|
176
|
-
done: boolean;
|
|
177
|
-
}
|
|
178
|
-
export type CryptoRequest = {
|
|
179
|
-
op: 'hmac';
|
|
180
|
-
algorithm: 'sha1' | 'sha256' | 'sha512';
|
|
181
|
-
key: string;
|
|
182
|
-
data: string;
|
|
183
|
-
encoding: 'hex' | 'base64';
|
|
184
|
-
} | {
|
|
185
|
-
op: 'sign';
|
|
186
|
-
algorithm: 'rsa-sha256';
|
|
187
|
-
key: string;
|
|
188
|
-
data: string;
|
|
189
|
-
encoding: 'hex' | 'base64';
|
|
190
|
-
} | {
|
|
191
|
-
op: 'hash';
|
|
192
|
-
algorithm: 'md5' | 'sha1' | 'sha256' | 'sha512';
|
|
193
|
-
data: string;
|
|
194
|
-
encoding: 'hex' | 'base64';
|
|
195
|
-
};
|
|
196
|
-
export interface CryptoResponse {
|
|
197
|
-
value: string;
|
|
198
|
-
}
|
|
199
|
-
export interface CacheGetRequest {
|
|
200
|
-
key: string;
|
|
201
|
-
}
|
|
202
|
-
export interface CacheEntry {
|
|
203
|
-
value: string;
|
|
204
|
-
expiresAt: string;
|
|
205
|
-
}
|
|
206
|
-
export interface CacheSetRequest {
|
|
207
|
-
key: string;
|
|
208
|
-
value: string;
|
|
209
|
-
ttlSeconds: number;
|
|
210
|
-
}
|
|
211
|
-
export interface SecretRevealRequest {
|
|
212
|
-
field: string;
|
|
213
|
-
}
|
|
214
|
-
export interface SecretRevealResponse {
|
|
215
|
-
value: string;
|
|
216
|
-
}
|
|
217
|
-
/** `emit` 的 payload:与 shared 的 `RunnerPullBatch` 去掉 `seq` 后同形;`seq` 由宿主编号。 */
|
|
218
|
-
/**
|
|
219
|
-
* `definition` 宿主调用的回复(connector `POST /runner/v1/runs/:runId/definition`):204 无正文,
|
|
220
|
-
* 或 200 带本次运行的生效限流(连接器声明与连接覆盖取小)。guest 用 `rateLimit.concurrency` 收紧 `ctx.map` 的并发。
|
|
221
|
-
*/
|
|
222
|
-
export interface DefinitionReply {
|
|
223
|
-
rateLimit?: {
|
|
224
|
-
perSecond: number;
|
|
225
|
-
concurrency: number;
|
|
226
|
-
};
|
|
227
|
-
}
|
|
228
|
-
/** `declaration` 宿主调用的 payload(`discoverFirst` 的拉取作业在 discover 之后、拉取之前发一次),回复 null。 */
|
|
229
|
-
export interface DeclarationReport {
|
|
230
|
-
summary: DefinitionSummary;
|
|
231
|
-
discover: NormalizedDiscover;
|
|
232
|
-
}
|
|
233
|
-
/** `emit` 宿主调用的回复:`stop: true` 时 guest 不再发 `emit`,以 `stopped: true` 结束。其余字段(seq 等)guest 不看。 */
|
|
234
|
-
export interface EmitReply {
|
|
235
|
-
stop?: boolean;
|
|
236
|
-
}
|
|
237
|
-
export interface GuestPullBatch {
|
|
238
|
-
records: Array<{
|
|
239
|
-
table: string;
|
|
240
|
-
row: Record<string, unknown>;
|
|
241
|
-
}>;
|
|
242
|
-
removals: Array<{
|
|
243
|
-
table: string;
|
|
244
|
-
key: Record<string, unknown>;
|
|
245
|
-
}>;
|
|
246
|
-
checkpoint?: {
|
|
247
|
-
state: unknown;
|
|
248
|
-
};
|
|
249
|
-
logs: GuestLog[];
|
|
250
|
-
/** 自上一批以来丢弃的超大记录 / 删除标记条数;为 0 时不带。 */
|
|
251
|
-
dropped?: number;
|
|
252
|
-
}
|
|
253
|
-
/** 解析父进程消息(子进程侧);结构不合法时返回 null。 */
|
|
254
|
-
export declare function parseParentMessage(value: unknown): ParentMessage | null;
|
|
255
|
-
/**
|
|
256
|
-
* `parseChildMessage` 拒绝一条 `emit` 时用来区分原因:记录或删除标记落在作业没声明的表上时返回第一张这样的表名,
|
|
257
|
-
* 宿主据此按 `SCHEMA_ERROR` 结束运行(与 guest 自己检查到时同一个错误码),而不是按子进程崩溃处理;其他情况返回 null。
|
|
258
|
-
*/
|
|
259
|
-
export declare function undeclaredEmitTable(value: unknown, job: GuestJob, options?: ParseChildOptions): string | null;
|
|
260
|
-
/** `parseChildMessage` 的运行期上下文。 */
|
|
261
|
-
export interface ParseChildOptions {
|
|
262
|
-
/**
|
|
263
|
-
* `discoverFirst` 的拉取作业:本次运行 `declaration` 上报的该数据流的表(`emit` 的表必须在其中)。
|
|
264
|
-
* 其他作业忽略,按 `job.tables` 校验。
|
|
265
|
-
*/
|
|
266
|
-
tables?: readonly string[];
|
|
267
|
-
/** 本次运行是否已经上报过 `declaration`:为 true 时再来的 `declaration` 调用不合法(协议错误)。 */
|
|
268
|
-
declared?: boolean;
|
|
269
|
-
}
|
|
270
|
-
/**
|
|
271
|
-
* 解析子进程消息(父进程侧)并重建一份干净的对象;结构不合法时返回 null(父进程按崩溃处理)。
|
|
272
|
-
* 宿主调用的 payload 按方法校验:`definition` 只出现在 discover / check / pull 作业,`declaration` 只出现在
|
|
273
|
-
* `discoverFirst` 的拉取作业且每次运行至多一次(`options.declared`),`emit` 只出现在 pull 作业且表必须在 `job.tables`(`discoverFirst` 时为 `options.tables`)里,
|
|
274
|
-
* `secret.reveal` 的字段必须在 `job.secretFields` 里;结果的 `kind` 必须与作业一致。
|
|
275
|
-
*/
|
|
276
|
-
export declare function parseChildMessage(value: unknown, job: GuestJob, options?: ParseChildOptions): ChildMessage | null;
|
package/runtime/protocol.js
DELETED
|
@@ -1,409 +0,0 @@
|
|
|
1
|
-
export const HOST_METHODS = Object.freeze([
|
|
2
|
-
'definition', 'declaration', 'http', 'db.query', 'db.next', 'db.close', 'crypto', 'cache.get', 'cache.set', 'secret.reveal', 'emit',
|
|
3
|
-
]);
|
|
4
|
-
export const GUEST_FAILURE_CODES = Object.freeze([
|
|
5
|
-
'CONNECTOR_LOAD_FAILED', 'CONFIG_INVALID', 'SCHEMA_ERROR', 'FATAL_ERROR', 'AUTH_ERROR', 'TRANSIENT_ERROR', 'PUSH_UNKNOWN', 'CANCELED',
|
|
6
|
-
]);
|
|
7
|
-
const HTTP_METHODS = new Set(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD']);
|
|
8
|
-
const BODY_ENCODINGS = new Set(['utf8', 'base64']);
|
|
9
|
-
const DIGEST_ENCODINGS = new Set(['hex', 'base64']);
|
|
10
|
-
const HMAC_ALGORITHMS = new Set(['sha1', 'sha256', 'sha512']);
|
|
11
|
-
const HASH_ALGORITHMS = new Set(['md5', 'sha1', 'sha256', 'sha512']);
|
|
12
|
-
const LOG_LEVELS = new Set(['info', 'warn', 'error']);
|
|
13
|
-
const SYNC_MODES = new Set(['full', 'incremental']);
|
|
14
|
-
const SNAPSHOTS = new Set(['complete', 'partial']);
|
|
15
|
-
const HOST_METHOD_SET = new Set(HOST_METHODS);
|
|
16
|
-
const FAILURE_CODE_SET = new Set(GUEST_FAILURE_CODES);
|
|
17
|
-
function isRecord(value) {
|
|
18
|
-
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
19
|
-
}
|
|
20
|
-
function isStringArray(value) {
|
|
21
|
-
return Array.isArray(value) && value.every((item) => typeof item === 'string');
|
|
22
|
-
}
|
|
23
|
-
function isStringRecord(value) {
|
|
24
|
-
return isRecord(value) && Object.values(value).every((item) => typeof item === 'string');
|
|
25
|
-
}
|
|
26
|
-
function isId(value) {
|
|
27
|
-
return typeof value === 'number' && Number.isSafeInteger(value) && value > 0;
|
|
28
|
-
}
|
|
29
|
-
function parsePushRequest(value) {
|
|
30
|
-
if (!isRecord(value))
|
|
31
|
-
return null;
|
|
32
|
-
const { requestId, push, receivedAt, headers, body } = value;
|
|
33
|
-
if (typeof requestId !== 'string' || typeof push !== 'string' || typeof receivedAt !== 'string' || !isStringRecord(headers) || typeof body !== 'string')
|
|
34
|
-
return null;
|
|
35
|
-
return { requestId, push, receivedAt, headers: { ...headers }, body };
|
|
36
|
-
}
|
|
37
|
-
function parseJob(value) {
|
|
38
|
-
if (!isRecord(value) || !isRecord(value.config) || !isStringArray(value.secretFields))
|
|
39
|
-
return null;
|
|
40
|
-
const config = value.config;
|
|
41
|
-
const secretFields = [...value.secretFields];
|
|
42
|
-
if (value.kind === 'push') {
|
|
43
|
-
if (!Array.isArray(value.requests))
|
|
44
|
-
return null;
|
|
45
|
-
const requests = [];
|
|
46
|
-
for (const item of value.requests) {
|
|
47
|
-
const request = parsePushRequest(item);
|
|
48
|
-
if (!request)
|
|
49
|
-
return null;
|
|
50
|
-
requests.push(request);
|
|
51
|
-
}
|
|
52
|
-
return { kind: 'push', config, secretFields, requests };
|
|
53
|
-
}
|
|
54
|
-
if (value.kind === 'discover')
|
|
55
|
-
return { kind: 'discover', config, secretFields };
|
|
56
|
-
if (value.kind === 'check')
|
|
57
|
-
return { kind: 'check', config, secretFields };
|
|
58
|
-
if (value.kind === 'pull') {
|
|
59
|
-
const { stream, mode, streamConfig, tables, discoverFirst } = value;
|
|
60
|
-
if (typeof stream !== 'string' || typeof mode !== 'string' || !SYNC_MODES.has(mode) || !isRecord(streamConfig) || !isStringArray(tables))
|
|
61
|
-
return null;
|
|
62
|
-
if (discoverFirst !== undefined && typeof discoverFirst !== 'boolean')
|
|
63
|
-
return null;
|
|
64
|
-
return {
|
|
65
|
-
kind: 'pull', config, secretFields, stream, mode: mode, state: value.state, streamConfig, tables: [...tables],
|
|
66
|
-
...(discoverFirst === true ? { discoverFirst: true } : {}),
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
return null;
|
|
70
|
-
}
|
|
71
|
-
function parseHostError(value) {
|
|
72
|
-
if (!isRecord(value) || typeof value.code !== 'string' || typeof value.message !== 'string')
|
|
73
|
-
return null;
|
|
74
|
-
const error = { code: value.code, message: value.message };
|
|
75
|
-
if (value.status !== undefined) {
|
|
76
|
-
if (typeof value.status !== 'number' || !Number.isInteger(value.status))
|
|
77
|
-
return null;
|
|
78
|
-
error.status = value.status;
|
|
79
|
-
}
|
|
80
|
-
if (value.retryAfterMs !== undefined) {
|
|
81
|
-
if (typeof value.retryAfterMs !== 'number' || !Number.isFinite(value.retryAfterMs) || value.retryAfterMs < 0)
|
|
82
|
-
return null;
|
|
83
|
-
error.retryAfterMs = value.retryAfterMs;
|
|
84
|
-
}
|
|
85
|
-
return error;
|
|
86
|
-
}
|
|
87
|
-
export function parseParentMessage(value) {
|
|
88
|
-
if (!isRecord(value))
|
|
89
|
-
return null;
|
|
90
|
-
switch (value.type) {
|
|
91
|
-
case 'execute': {
|
|
92
|
-
const { guest, code, expect } = value;
|
|
93
|
-
if (typeof guest !== 'string' || typeof code !== 'string')
|
|
94
|
-
return null;
|
|
95
|
-
if (!isRecord(expect) || typeof expect.name !== 'string' || typeof expect.version !== 'string')
|
|
96
|
-
return null;
|
|
97
|
-
const job = parseJob(value.job);
|
|
98
|
-
return job ? { type: 'execute', guest, code, expect: { name: expect.name, version: expect.version }, job } : null;
|
|
99
|
-
}
|
|
100
|
-
case 'reply': {
|
|
101
|
-
if (!isId(value.id))
|
|
102
|
-
return null;
|
|
103
|
-
if (value.ok === true)
|
|
104
|
-
return { type: 'reply', id: value.id, ok: true, value: value.value };
|
|
105
|
-
if (value.ok !== false)
|
|
106
|
-
return null;
|
|
107
|
-
const error = parseHostError(value.error);
|
|
108
|
-
return error ? { type: 'reply', id: value.id, ok: false, error } : null;
|
|
109
|
-
}
|
|
110
|
-
case 'cancel':
|
|
111
|
-
return { type: 'cancel' };
|
|
112
|
-
default:
|
|
113
|
-
return null;
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
function parseLogs(value) {
|
|
117
|
-
if (!Array.isArray(value))
|
|
118
|
-
return null;
|
|
119
|
-
const logs = [];
|
|
120
|
-
for (const entry of value) {
|
|
121
|
-
if (!isRecord(entry) || typeof entry.at !== 'string' || typeof entry.level !== 'string' || !LOG_LEVELS.has(entry.level) || typeof entry.message !== 'string')
|
|
122
|
-
return null;
|
|
123
|
-
if (entry.requestId !== undefined && typeof entry.requestId !== 'string')
|
|
124
|
-
return null;
|
|
125
|
-
logs.push({
|
|
126
|
-
at: entry.at,
|
|
127
|
-
level: entry.level,
|
|
128
|
-
message: entry.message,
|
|
129
|
-
...(entry.requestId !== undefined ? { requestId: entry.requestId } : {}),
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
return logs;
|
|
133
|
-
}
|
|
134
|
-
function parseSummary(value) {
|
|
135
|
-
if (!isRecord(value))
|
|
136
|
-
return null;
|
|
137
|
-
const { name, version, hosts, db, rateLimit, pushes, streams, secretFields, exposeToScript, config } = value;
|
|
138
|
-
if (typeof name !== 'string' || typeof version !== 'string')
|
|
139
|
-
return null;
|
|
140
|
-
if (!isStringArray(hosts) || !isStringArray(pushes) || !isStringArray(streams) || !isStringArray(secretFields) || !isStringArray(exposeToScript))
|
|
141
|
-
return null;
|
|
142
|
-
if (db !== null && !(isRecord(db) && db.engine === 'postgresql'))
|
|
143
|
-
return null;
|
|
144
|
-
let parsedRateLimit = null;
|
|
145
|
-
if (rateLimit !== null) {
|
|
146
|
-
if (!isRecord(rateLimit) || typeof rateLimit.perSecond !== 'number' || typeof rateLimit.concurrency !== 'number')
|
|
147
|
-
return null;
|
|
148
|
-
parsedRateLimit = { perSecond: rateLimit.perSecond, concurrency: rateLimit.concurrency };
|
|
149
|
-
}
|
|
150
|
-
return {
|
|
151
|
-
name, version, hosts: [...hosts], db: db === null ? null : { engine: 'postgresql' }, rateLimit: parsedRateLimit,
|
|
152
|
-
pushes: [...pushes], streams: [...streams], secretFields: [...secretFields], exposeToScript: [...exposeToScript],
|
|
153
|
-
...(isRecord(config) ? { config } : {}),
|
|
154
|
-
};
|
|
155
|
-
}
|
|
156
|
-
function parseTables(value) {
|
|
157
|
-
if (!isRecord(value))
|
|
158
|
-
return null;
|
|
159
|
-
const tables = {};
|
|
160
|
-
for (const [name, table] of Object.entries(value)) {
|
|
161
|
-
if (!isRecord(table) || !isRecord(table.columns) || !isStringArray(table.primaryKey))
|
|
162
|
-
return null;
|
|
163
|
-
tables[name] = table;
|
|
164
|
-
}
|
|
165
|
-
return tables;
|
|
166
|
-
}
|
|
167
|
-
function parseDiscover(value) {
|
|
168
|
-
if (!isRecord(value) || !isRecord(value.streams) || !isRecord(value.pushes))
|
|
169
|
-
return null;
|
|
170
|
-
const result = { streams: {}, pushes: {} };
|
|
171
|
-
for (const [name, stream] of Object.entries(value.streams)) {
|
|
172
|
-
if (!isRecord(stream) || !isStringArray(stream.syncModes) || !stream.syncModes.every((mode) => SYNC_MODES.has(mode)))
|
|
173
|
-
return null;
|
|
174
|
-
if (typeof stream.snapshot !== 'string' || !SNAPSHOTS.has(stream.snapshot))
|
|
175
|
-
return null;
|
|
176
|
-
if (stream.params !== undefined && !(isRecord(stream.params) && stream.params.kind === 'object'))
|
|
177
|
-
return null;
|
|
178
|
-
const tables = parseTables(stream.tables);
|
|
179
|
-
if (!tables)
|
|
180
|
-
return null;
|
|
181
|
-
result.streams[name] = {
|
|
182
|
-
tables,
|
|
183
|
-
syncModes: [...stream.syncModes],
|
|
184
|
-
snapshot: stream.snapshot,
|
|
185
|
-
...(stream.params !== undefined ? { params: stream.params } : {}),
|
|
186
|
-
};
|
|
187
|
-
}
|
|
188
|
-
for (const [name, push] of Object.entries(value.pushes)) {
|
|
189
|
-
if (!isRecord(push))
|
|
190
|
-
return null;
|
|
191
|
-
const tables = parseTables(push.tables);
|
|
192
|
-
if (!tables)
|
|
193
|
-
return null;
|
|
194
|
-
result.pushes[name] = { tables };
|
|
195
|
-
}
|
|
196
|
-
return result;
|
|
197
|
-
}
|
|
198
|
-
function parsePushResult(value, requestIds) {
|
|
199
|
-
const { records, removals, rejected } = value;
|
|
200
|
-
if (!Array.isArray(records) || !Array.isArray(removals) || !Array.isArray(rejected))
|
|
201
|
-
return null;
|
|
202
|
-
const logs = parseLogs(value.logs);
|
|
203
|
-
if (!logs)
|
|
204
|
-
return null;
|
|
205
|
-
const result = { kind: 'push', records: [], removals: [], rejected: [], logs };
|
|
206
|
-
for (const item of records) {
|
|
207
|
-
if (!isRecord(item) || typeof item.requestId !== 'string' || !requestIds.has(item.requestId))
|
|
208
|
-
return null;
|
|
209
|
-
if (typeof item.table !== 'string' || !isRecord(item.row))
|
|
210
|
-
return null;
|
|
211
|
-
result.records.push({ requestId: item.requestId, table: item.table, row: item.row });
|
|
212
|
-
}
|
|
213
|
-
for (const item of removals) {
|
|
214
|
-
if (!isRecord(item) || typeof item.requestId !== 'string' || !requestIds.has(item.requestId))
|
|
215
|
-
return null;
|
|
216
|
-
if (typeof item.table !== 'string' || !isRecord(item.key))
|
|
217
|
-
return null;
|
|
218
|
-
result.removals.push({ requestId: item.requestId, table: item.table, key: item.key });
|
|
219
|
-
}
|
|
220
|
-
for (const item of rejected) {
|
|
221
|
-
if (!isRecord(item) || typeof item.requestId !== 'string' || !requestIds.has(item.requestId))
|
|
222
|
-
return null;
|
|
223
|
-
if (typeof item.code !== 'string' || typeof item.message !== 'string')
|
|
224
|
-
return null;
|
|
225
|
-
result.rejected.push({ requestId: item.requestId, code: item.code, message: item.message });
|
|
226
|
-
}
|
|
227
|
-
return result;
|
|
228
|
-
}
|
|
229
|
-
function parseResult(value, job) {
|
|
230
|
-
if (!isRecord(value) || value.kind !== job.kind)
|
|
231
|
-
return null;
|
|
232
|
-
if (job.kind === 'push')
|
|
233
|
-
return parsePushResult(value, new Set(job.requests.map((request) => request.requestId)));
|
|
234
|
-
const logs = parseLogs(value.logs);
|
|
235
|
-
if (!logs)
|
|
236
|
-
return null;
|
|
237
|
-
if (job.kind === 'discover') {
|
|
238
|
-
const summary = parseSummary(value.summary);
|
|
239
|
-
const discover = parseDiscover(value.discover);
|
|
240
|
-
return summary && discover ? { kind: 'discover', summary, discover, logs } : null;
|
|
241
|
-
}
|
|
242
|
-
if (job.kind === 'check')
|
|
243
|
-
return value.ok === true ? { kind: 'check', ok: true, logs } : null;
|
|
244
|
-
const emittedBatches = value.emittedBatches;
|
|
245
|
-
if (typeof emittedBatches !== 'number' || !Number.isSafeInteger(emittedBatches) || emittedBatches < 0)
|
|
246
|
-
return null;
|
|
247
|
-
if (value.stopped !== undefined && typeof value.stopped !== 'boolean')
|
|
248
|
-
return null;
|
|
249
|
-
return { kind: 'pull', emittedBatches, ...(value.stopped === true ? { stopped: true } : {}), logs };
|
|
250
|
-
}
|
|
251
|
-
function parseDeclaration(value) {
|
|
252
|
-
if (!isRecord(value))
|
|
253
|
-
return null;
|
|
254
|
-
const summary = parseSummary(value.summary);
|
|
255
|
-
const discover = parseDiscover(value.discover);
|
|
256
|
-
return summary && discover ? { summary, discover } : null;
|
|
257
|
-
}
|
|
258
|
-
function parseBatch(value, tables) {
|
|
259
|
-
if (!isRecord(value) || !Array.isArray(value.records) || !Array.isArray(value.removals))
|
|
260
|
-
return null;
|
|
261
|
-
const logs = parseLogs(value.logs);
|
|
262
|
-
if (!logs)
|
|
263
|
-
return null;
|
|
264
|
-
const batch = { records: [], removals: [], logs };
|
|
265
|
-
for (const item of value.records) {
|
|
266
|
-
if (!isRecord(item) || typeof item.table !== 'string' || !tables.has(item.table) || !isRecord(item.row))
|
|
267
|
-
return null;
|
|
268
|
-
batch.records.push({ table: item.table, row: item.row });
|
|
269
|
-
}
|
|
270
|
-
for (const item of value.removals) {
|
|
271
|
-
if (!isRecord(item) || typeof item.table !== 'string' || !tables.has(item.table) || !isRecord(item.key))
|
|
272
|
-
return null;
|
|
273
|
-
batch.removals.push({ table: item.table, key: item.key });
|
|
274
|
-
}
|
|
275
|
-
if (value.checkpoint !== undefined) {
|
|
276
|
-
if (!isRecord(value.checkpoint) || !Object.hasOwn(value.checkpoint, 'state'))
|
|
277
|
-
return null;
|
|
278
|
-
batch.checkpoint = { state: value.checkpoint.state };
|
|
279
|
-
}
|
|
280
|
-
if (value.dropped !== undefined) {
|
|
281
|
-
if (typeof value.dropped !== 'number' || !Number.isSafeInteger(value.dropped) || value.dropped < 0)
|
|
282
|
-
return null;
|
|
283
|
-
batch.dropped = value.dropped;
|
|
284
|
-
}
|
|
285
|
-
return batch;
|
|
286
|
-
}
|
|
287
|
-
function parseHttpRequest(value) {
|
|
288
|
-
if (!isRecord(value))
|
|
289
|
-
return null;
|
|
290
|
-
const { method, url, headers, query, body, bodyEncoding, timeoutMs } = value;
|
|
291
|
-
if (typeof method !== 'string' || !HTTP_METHODS.has(method) || typeof url !== 'string' || !isStringRecord(headers))
|
|
292
|
-
return null;
|
|
293
|
-
if (!isRecord(query) || !Object.values(query).every((item) => typeof item === 'string' || isStringArray(item)))
|
|
294
|
-
return null;
|
|
295
|
-
if (body !== null && typeof body !== 'string')
|
|
296
|
-
return null;
|
|
297
|
-
if (typeof bodyEncoding !== 'string' || !BODY_ENCODINGS.has(bodyEncoding))
|
|
298
|
-
return null;
|
|
299
|
-
if (timeoutMs !== undefined && (typeof timeoutMs !== 'number' || !Number.isFinite(timeoutMs) || timeoutMs <= 0))
|
|
300
|
-
return null;
|
|
301
|
-
const parsedQuery = {};
|
|
302
|
-
for (const [key, item] of Object.entries(query))
|
|
303
|
-
parsedQuery[key] = Array.isArray(item) ? [...item] : item;
|
|
304
|
-
return {
|
|
305
|
-
method: method, url, headers: { ...headers }, query: parsedQuery, body,
|
|
306
|
-
bodyEncoding: bodyEncoding, ...(timeoutMs !== undefined ? { timeoutMs } : {}),
|
|
307
|
-
};
|
|
308
|
-
}
|
|
309
|
-
function parseCryptoRequest(value) {
|
|
310
|
-
if (!isRecord(value) || typeof value.data !== 'string' || typeof value.algorithm !== 'string')
|
|
311
|
-
return null;
|
|
312
|
-
if (typeof value.encoding !== 'string' || !DIGEST_ENCODINGS.has(value.encoding))
|
|
313
|
-
return null;
|
|
314
|
-
const { data, algorithm } = value;
|
|
315
|
-
const encoding = value.encoding;
|
|
316
|
-
if (value.op === 'hash') {
|
|
317
|
-
return HASH_ALGORITHMS.has(algorithm) ? { op: 'hash', algorithm: algorithm, data, encoding } : null;
|
|
318
|
-
}
|
|
319
|
-
if (typeof value.key !== 'string')
|
|
320
|
-
return null;
|
|
321
|
-
if (value.op === 'hmac') {
|
|
322
|
-
return HMAC_ALGORITHMS.has(algorithm) ? { op: 'hmac', algorithm: algorithm, key: value.key, data, encoding } : null;
|
|
323
|
-
}
|
|
324
|
-
if (value.op === 'sign')
|
|
325
|
-
return algorithm === 'rsa-sha256' ? { op: 'sign', algorithm: 'rsa-sha256', key: value.key, data, encoding } : null;
|
|
326
|
-
return null;
|
|
327
|
-
}
|
|
328
|
-
function parsePayload(method, payload, job, options) {
|
|
329
|
-
switch (method) {
|
|
330
|
-
case 'definition':
|
|
331
|
-
return job.kind === 'push' ? null : parseSummary(payload);
|
|
332
|
-
case 'declaration':
|
|
333
|
-
if (options.declared === true)
|
|
334
|
-
return null;
|
|
335
|
-
return job.kind === 'pull' && job.discoverFirst === true ? parseDeclaration(payload) : null;
|
|
336
|
-
case 'http':
|
|
337
|
-
return parseHttpRequest(payload);
|
|
338
|
-
case 'db.query':
|
|
339
|
-
return isRecord(payload) && typeof payload.sql === 'string' && Array.isArray(payload.params) ? { sql: payload.sql, params: [...payload.params] } : null;
|
|
340
|
-
case 'db.next':
|
|
341
|
-
case 'db.close':
|
|
342
|
-
return isRecord(payload) && typeof payload.cursorId === 'string' ? { cursorId: payload.cursorId } : null;
|
|
343
|
-
case 'crypto':
|
|
344
|
-
return parseCryptoRequest(payload);
|
|
345
|
-
case 'cache.get':
|
|
346
|
-
return isRecord(payload) && typeof payload.key === 'string' ? { key: payload.key } : null;
|
|
347
|
-
case 'cache.set': {
|
|
348
|
-
if (!isRecord(payload) || typeof payload.key !== 'string' || typeof payload.value !== 'string')
|
|
349
|
-
return null;
|
|
350
|
-
const ttl = payload.ttlSeconds;
|
|
351
|
-
return typeof ttl === 'number' && Number.isSafeInteger(ttl) && ttl > 0 ? { key: payload.key, value: payload.value, ttlSeconds: ttl } : null;
|
|
352
|
-
}
|
|
353
|
-
case 'secret.reveal':
|
|
354
|
-
return isRecord(payload) && typeof payload.field === 'string' && job.secretFields.includes(payload.field) ? { field: payload.field } : null;
|
|
355
|
-
case 'emit':
|
|
356
|
-
if (job.kind !== 'pull')
|
|
357
|
-
return null;
|
|
358
|
-
return parseBatch(payload, new Set(job.discoverFirst === true ? options.tables ?? [] : job.tables));
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
export function undeclaredEmitTable(value, job, options = {}) {
|
|
362
|
-
if (job.kind !== 'pull' || !isRecord(value) || value.type !== 'call' || value.method !== 'emit' || !isRecord(value.payload))
|
|
363
|
-
return null;
|
|
364
|
-
const allowed = new Set(job.discoverFirst === true ? options.tables ?? [] : job.tables);
|
|
365
|
-
for (const key of ['records', 'removals']) {
|
|
366
|
-
const items = value.payload[key];
|
|
367
|
-
if (!Array.isArray(items))
|
|
368
|
-
continue;
|
|
369
|
-
for (const item of items) {
|
|
370
|
-
if (isRecord(item) && typeof item.table === 'string' && !allowed.has(item.table))
|
|
371
|
-
return item.table;
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
return null;
|
|
375
|
-
}
|
|
376
|
-
export function parseChildMessage(value, job, options = {}) {
|
|
377
|
-
if (!isRecord(value))
|
|
378
|
-
return null;
|
|
379
|
-
switch (value.type) {
|
|
380
|
-
case 'ready':
|
|
381
|
-
return { type: 'ready' };
|
|
382
|
-
case 'call': {
|
|
383
|
-
if (!isId(value.id) || typeof value.method !== 'string' || !HOST_METHOD_SET.has(value.method))
|
|
384
|
-
return null;
|
|
385
|
-
const method = value.method;
|
|
386
|
-
const payload = parsePayload(method, value.payload, job, options);
|
|
387
|
-
return payload === null ? null : { type: 'call', id: value.id, method, payload };
|
|
388
|
-
}
|
|
389
|
-
case 'result': {
|
|
390
|
-
const result = parseResult(value.result, job);
|
|
391
|
-
return result ? { type: 'result', result } : null;
|
|
392
|
-
}
|
|
393
|
-
case 'failure': {
|
|
394
|
-
if (typeof value.code !== 'string' || !FAILURE_CODE_SET.has(value.code) || typeof value.message !== 'string')
|
|
395
|
-
return null;
|
|
396
|
-
if (value.stack !== undefined && typeof value.stack !== 'string')
|
|
397
|
-
return null;
|
|
398
|
-
const logs = parseLogs(value.logs);
|
|
399
|
-
if (!logs)
|
|
400
|
-
return null;
|
|
401
|
-
return {
|
|
402
|
-
type: 'failure', code: value.code, message: value.message,
|
|
403
|
-
...(value.stack !== undefined ? { stack: value.stack } : {}), logs,
|
|
404
|
-
};
|
|
405
|
-
}
|
|
406
|
-
default:
|
|
407
|
-
return null;
|
|
408
|
-
}
|
|
409
|
-
}
|