@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.
Files changed (185) hide show
  1. package/README.md +158 -139
  2. package/package.json +19 -28
  3. package/scripts/build.ts +188 -0
  4. package/src/define.ts +267 -0
  5. package/src/descriptor.ts +116 -0
  6. package/src/errors.ts +105 -0
  7. package/src/index.ts +108 -0
  8. package/src/internal/location.ts +23 -0
  9. package/src/runtime/guest/bridge.ts +238 -0
  10. package/src/runtime/guest/cache.ts +43 -0
  11. package/src/runtime/guest/check.ts +17 -0
  12. package/src/runtime/guest/crypto.ts +166 -0
  13. package/src/runtime/guest/ctx.ts +157 -0
  14. package/src/runtime/guest/db.ts +59 -0
  15. package/src/runtime/guest/failure.ts +69 -0
  16. package/src/runtime/guest/http.ts +194 -0
  17. package/src/runtime/guest/index.ts +102 -0
  18. package/{runtime/guest/limits.d.ts → src/runtime/guest/limits.ts} +12 -12
  19. package/src/runtime/guest/loader.ts +210 -0
  20. package/src/runtime/guest/log.ts +47 -0
  21. package/src/runtime/guest/map.ts +45 -0
  22. package/src/runtime/guest/operation.ts +193 -0
  23. package/src/runtime/guest/paginate.ts +169 -0
  24. package/src/runtime/guest/pull.ts +177 -0
  25. package/src/runtime/guest/push.ts +92 -0
  26. package/src/runtime/guest/signal.ts +14 -0
  27. package/src/runtime/guest/suggest.ts +51 -0
  28. package/src/runtime/guest/time.ts +137 -0
  29. package/src/runtime/guest-runtime.ts +75 -0
  30. package/src/runtime/index.ts +53 -0
  31. package/src/runtime/protocol.ts +557 -0
  32. package/src/runtime/session.ts +216 -0
  33. package/src/testing/child.ts +21 -0
  34. package/src/testing/compliance.ts +343 -0
  35. package/src/testing/engine.ts +445 -0
  36. package/src/testing/fixtures.ts +591 -0
  37. package/src/testing/gateway.ts +482 -0
  38. package/src/testing/import-guard.ts +221 -0
  39. package/src/testing/index.ts +43 -0
  40. package/src/testing/local-db.ts +226 -0
  41. package/src/testing/mock-external-system.ts +249 -0
  42. package/src/testing/pinned-http.ts +144 -0
  43. package/src/testing/recorder.ts +140 -0
  44. package/src/testing/redaction.ts +94 -0
  45. package/src/testing/replay.ts +437 -0
  46. package/src/testing/run-tests.ts +115 -0
  47. package/src/testing/schema.ts +70 -0
  48. package/src/testing/source-loader.ts +374 -0
  49. package/src/testing/types.ts +78 -0
  50. package/src/types.ts +329 -0
  51. package/src/validate.ts +267 -0
  52. package/test/build.test.ts +159 -0
  53. package/test/define.test-d.ts +182 -0
  54. package/test/fixtures/acceptance.ts +156 -0
  55. package/test/fixtures/connectors/http-pull/.ontos/descriptor.json +72 -0
  56. package/test/fixtures/connectors/http-pull/.ontos/types.ts +61 -0
  57. package/test/fixtures/connectors/http-pull/package.json +5 -0
  58. package/test/fixtures/connectors/http-pull/streams/items/index.ts +37 -0
  59. package/test/fixtures/connectors/http-pull/streams/items/map.ts +12 -0
  60. package/test/fixtures/connectors/http-pull/streams/items/tests/basic/case.json +15 -0
  61. package/test/fixtures/connectors/http-pull/streams/items/tests/basic/exchanges.ndjson +2 -0
  62. package/test/fixtures/connectors/pg-pull/.ontos/descriptor.json +151 -0
  63. package/test/fixtures/connectors/pg-pull/.ontos/types.ts +62 -0
  64. package/test/fixtures/connectors/pg-pull/lib/sql.ts +14 -0
  65. package/test/fixtures/connectors/pg-pull/package.json +5 -0
  66. package/test/fixtures/connectors/pg-pull/streams/customers/index.ts +30 -0
  67. package/test/fixtures/connectors/pg-pull/streams/customers/tests/customers-full/case.json +15 -0
  68. package/test/fixtures/connectors/pg-pull/streams/customers/tests/customers-full/exchanges.ndjson +3 -0
  69. package/test/fixtures/connectors/pg-pull/streams/orders/index.ts +32 -0
  70. package/test/fixtures/descriptor.ts +54 -0
  71. package/test/fixtures/kingdee-example.ts +82 -0
  72. package/test/fixtures/record-acceptance.ts +32 -0
  73. package/test/runtime/ctx.test.ts +434 -0
  74. package/test/runtime/helpers.ts +157 -0
  75. package/test/runtime/jobs.test.ts +444 -0
  76. package/test/runtime/operation.test.ts +175 -0
  77. package/test/runtime/session.test.ts +229 -0
  78. package/test/testing/acceptance-fixtures.test.ts +69 -0
  79. package/test/testing/compliance.test.ts +247 -0
  80. package/test/testing/engine.test.ts +283 -0
  81. package/test/testing/fixtures.test.ts +221 -0
  82. package/test/testing/gateway.test.ts +337 -0
  83. package/test/testing/import-guard.test.ts +45 -0
  84. package/test/testing/mock-external-system.test.ts +144 -0
  85. package/test/testing/operation-fixtures.test.ts +160 -0
  86. package/test/testing/recorder.test.ts +163 -0
  87. package/test/testing/redaction.test.ts +54 -0
  88. package/test/testing/replay.test.ts +207 -0
  89. package/test/testing/run-tests.test.ts +137 -0
  90. package/test/testing/source-loader.test.ts +220 -0
  91. package/test/validate-config.test.ts +104 -0
  92. package/tsconfig.build.json +23 -0
  93. package/tsconfig.json +19 -0
  94. package/cjs/index.cjs +0 -1015
  95. package/cjs/runtime.cjs +0 -752
  96. package/cjs/testing.cjs +0 -3591
  97. package/errors.d.ts +0 -17
  98. package/errors.js +0 -53
  99. package/guest.cjs +0 -2659
  100. package/index.d.ts +0 -13
  101. package/index.js +0 -7
  102. package/internal/location.d.ts +0 -6
  103. package/internal/location.js +0 -8
  104. package/presentation.d.ts +0 -38
  105. package/presentation.js +0 -268
  106. package/runtime/guest/bridge.d.ts +0 -53
  107. package/runtime/guest/bridge.js +0 -187
  108. package/runtime/guest/cache.d.ts +0 -3
  109. package/runtime/guest/cache.js +0 -42
  110. package/runtime/guest/crypto.d.ts +0 -13
  111. package/runtime/guest/crypto.js +0 -177
  112. package/runtime/guest/ctx.d.ts +0 -30
  113. package/runtime/guest/ctx.js +0 -124
  114. package/runtime/guest/db.d.ts +0 -6
  115. package/runtime/guest/db.js +0 -59
  116. package/runtime/guest/discover.d.ts +0 -29
  117. package/runtime/guest/discover.js +0 -51
  118. package/runtime/guest/failure.d.ts +0 -24
  119. package/runtime/guest/failure.js +0 -63
  120. package/runtime/guest/http.d.ts +0 -4
  121. package/runtime/guest/http.js +0 -204
  122. package/runtime/guest/index.d.ts +0 -12
  123. package/runtime/guest/index.js +0 -89
  124. package/runtime/guest/limits.js +0 -12
  125. package/runtime/guest/loader.d.ts +0 -15
  126. package/runtime/guest/loader.js +0 -42
  127. package/runtime/guest/log.d.ts +0 -10
  128. package/runtime/guest/log.js +0 -36
  129. package/runtime/guest/map.d.ts +0 -4
  130. package/runtime/guest/map.js +0 -45
  131. package/runtime/guest/paginate.d.ts +0 -6
  132. package/runtime/guest/paginate.js +0 -180
  133. package/runtime/guest/pull.d.ts +0 -12
  134. package/runtime/guest/pull.js +0 -150
  135. package/runtime/guest/push.d.ts +0 -18
  136. package/runtime/guest/push.js +0 -80
  137. package/runtime/guest/signal.d.ts +0 -3
  138. package/runtime/guest/signal.js +0 -12
  139. package/runtime/guest/time.d.ts +0 -5
  140. package/runtime/guest/time.js +0 -127
  141. package/runtime/guest-runtime.d.ts +0 -7
  142. package/runtime/guest-runtime.js +0 -51
  143. package/runtime/index.d.ts +0 -18
  144. package/runtime/index.js +0 -3
  145. package/runtime/protocol.d.ts +0 -276
  146. package/runtime/protocol.js +0 -409
  147. package/runtime/session.d.ts +0 -12
  148. package/runtime/session.js +0 -191
  149. package/t.d.ts +0 -18
  150. package/t.js +0 -26
  151. package/testing/child.cjs +0 -350
  152. package/testing/child.d.ts +0 -1
  153. package/testing/child.js +0 -12
  154. package/testing/compliance.d.ts +0 -41
  155. package/testing/compliance.js +0 -291
  156. package/testing/engine.d.ts +0 -66
  157. package/testing/engine.js +0 -339
  158. package/testing/fixtures.d.ts +0 -145
  159. package/testing/fixtures.js +0 -407
  160. package/testing/gateway.d.ts +0 -65
  161. package/testing/gateway.js +0 -402
  162. package/testing/import-guard.d.ts +0 -57
  163. package/testing/import-guard.js +0 -187
  164. package/testing/index.d.ts +0 -33
  165. package/testing/index.js +0 -10
  166. package/testing/local-db.d.ts +0 -27
  167. package/testing/local-db.js +0 -181
  168. package/testing/pinned-http.d.ts +0 -14
  169. package/testing/pinned-http.js +0 -125
  170. package/testing/recorder.d.ts +0 -15
  171. package/testing/recorder.js +0 -116
  172. package/testing/redaction.d.ts +0 -28
  173. package/testing/redaction.js +0 -67
  174. package/testing/replay.d.ts +0 -50
  175. package/testing/replay.js +0 -313
  176. package/testing/schema.d.ts +0 -13
  177. package/testing/schema.js +0 -65
  178. package/testing/source-loader.d.ts +0 -19
  179. package/testing/source-loader.js +0 -238
  180. package/testing/types.d.ts +0 -79
  181. package/testing/types.js +0 -18
  182. package/types.d.ts +0 -302
  183. package/types.js +0 -13
  184. package/validate.d.ts +0 -78
  185. package/validate.js +0 -597
@@ -1,177 +0,0 @@
1
- import { call } from './bridge.js';
2
- const HMAC_ALGORITHMS = ['sha1', 'sha256', 'sha512'];
3
- const HASH_ALGORITHMS = ['md5', 'sha1', 'sha256', 'sha512'];
4
- const ENCODINGS = ['hex', 'base64'];
5
- const ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
6
- function encoding(value) {
7
- if (value === undefined)
8
- return 'hex';
9
- if (typeof value !== 'string' || !ENCODINGS.includes(value))
10
- throw new TypeError("encoding must be 'hex' or 'base64'");
11
- return value;
12
- }
13
- function text(value, what) {
14
- if (typeof value !== 'string')
15
- throw new TypeError(`${what} must be a string`);
16
- return value;
17
- }
18
- async function digest(request) {
19
- const response = await call('crypto', request);
20
- if (!response || typeof response.value !== 'string')
21
- throw new TypeError('crypto host call returned no value');
22
- return response.value;
23
- }
24
- export function utf8Encode(input) {
25
- const bytes = [];
26
- for (let i = 0; i < input.length; i += 1) {
27
- let code = input.charCodeAt(i);
28
- if (code >= 0xd800 && code <= 0xdbff && i + 1 < input.length) {
29
- const low = input.charCodeAt(i + 1);
30
- if (low >= 0xdc00 && low <= 0xdfff) {
31
- code = 0x10000 + ((code - 0xd800) << 10) + (low - 0xdc00);
32
- i += 1;
33
- }
34
- }
35
- if (code >= 0xd800 && code <= 0xdfff)
36
- code = 0xfffd;
37
- if (code < 0x80)
38
- bytes.push(code);
39
- else if (code < 0x800)
40
- bytes.push(0xc0 | (code >> 6), 0x80 | (code & 63));
41
- else if (code < 0x10000)
42
- bytes.push(0xe0 | (code >> 12), 0x80 | ((code >> 6) & 63), 0x80 | (code & 63));
43
- else
44
- bytes.push(0xf0 | (code >> 18), 0x80 | ((code >> 12) & 63), 0x80 | ((code >> 6) & 63), 0x80 | (code & 63));
45
- }
46
- return bytes;
47
- }
48
- export function utf8Length(input) {
49
- let length = 0;
50
- for (let i = 0; i < input.length; i += 1) {
51
- const code = input.charCodeAt(i);
52
- if (code < 0x80)
53
- length += 1;
54
- else if (code < 0x800)
55
- length += 2;
56
- else if (code >= 0xd800 && code <= 0xdbff && i + 1 < input.length) {
57
- const low = input.charCodeAt(i + 1);
58
- if (low >= 0xdc00 && low <= 0xdfff) {
59
- length += 4;
60
- i += 1;
61
- }
62
- else {
63
- length += 3;
64
- }
65
- }
66
- else
67
- length += 3;
68
- }
69
- return length;
70
- }
71
- function utf8Decode(bytes) {
72
- let out = '';
73
- let i = 0;
74
- while (i < bytes.length) {
75
- const b0 = bytes[i] ?? 0;
76
- let code = 0xfffd;
77
- let size = 1;
78
- const cont = (offset) => {
79
- const b = bytes[i + offset];
80
- return b !== undefined && (b & 0xc0) === 0x80 ? b & 63 : -1;
81
- };
82
- if (b0 < 0x80) {
83
- code = b0;
84
- }
85
- else if (b0 >= 0xc2 && b0 < 0xe0) {
86
- const b1 = cont(1);
87
- if (b1 >= 0) {
88
- code = ((b0 & 31) << 6) | b1;
89
- size = 2;
90
- }
91
- }
92
- else if (b0 >= 0xe0 && b0 < 0xf0) {
93
- const b1 = cont(1);
94
- const b2 = cont(2);
95
- if (b1 >= 0 && b2 >= 0) {
96
- const value = ((b0 & 15) << 12) | (b1 << 6) | b2;
97
- if (value >= 0x800 && (value < 0xd800 || value > 0xdfff)) {
98
- code = value;
99
- size = 3;
100
- }
101
- }
102
- }
103
- else if (b0 >= 0xf0 && b0 < 0xf5) {
104
- const b1 = cont(1);
105
- const b2 = cont(2);
106
- const b3 = cont(3);
107
- if (b1 >= 0 && b2 >= 0 && b3 >= 0) {
108
- const value = ((b0 & 7) << 18) | (b1 << 12) | (b2 << 6) | b3;
109
- if (value >= 0x10000 && value <= 0x10ffff) {
110
- code = value;
111
- size = 4;
112
- }
113
- }
114
- }
115
- out += String.fromCodePoint(code);
116
- i += size;
117
- }
118
- return out;
119
- }
120
- export function bytesToBase64(bytes) {
121
- let out = '';
122
- for (let i = 0; i < bytes.length; i += 3) {
123
- const b0 = bytes[i] ?? 0;
124
- const b1 = bytes[i + 1];
125
- const b2 = bytes[i + 2];
126
- const chunk = (b0 << 16) | ((b1 ?? 0) << 8) | (b2 ?? 0);
127
- out += ALPHABET.charAt((chunk >> 18) & 63) + ALPHABET.charAt((chunk >> 12) & 63);
128
- out += b1 === undefined ? '=' : ALPHABET.charAt((chunk >> 6) & 63);
129
- out += b2 === undefined ? '=' : ALPHABET.charAt(chunk & 63);
130
- }
131
- return out;
132
- }
133
- export function base64ToBytes(input) {
134
- const clean = input.replace(/[\s=]/g, '').replace(/-/g, '+').replace(/_/g, '/');
135
- const bytes = [];
136
- let buffer = 0;
137
- let bits = 0;
138
- for (let i = 0; i < clean.length; i += 1) {
139
- const value = ALPHABET.indexOf(clean.charAt(i));
140
- if (value < 0)
141
- throw new TypeError('invalid base64 text');
142
- buffer = (buffer << 6) | value;
143
- bits += 6;
144
- if (bits >= 8) {
145
- bits -= 8;
146
- bytes.push((buffer >> bits) & 0xff);
147
- }
148
- }
149
- return bytes;
150
- }
151
- export function base64Encode(input) {
152
- return bytesToBase64(utf8Encode(text(input, 'base64Encode input')));
153
- }
154
- export function base64Decode(input) {
155
- return utf8Decode(base64ToBytes(text(input, 'base64Decode input')));
156
- }
157
- export function createCrypto() {
158
- return Object.freeze({
159
- hmac(algorithm, key, data, enc) {
160
- if (!HMAC_ALGORITHMS.includes(algorithm))
161
- return Promise.reject(new TypeError(`unsupported hmac algorithm ${String(algorithm)}`));
162
- return Promise.resolve().then(() => digest({ op: 'hmac', algorithm, key: text(key, 'hmac key'), data: text(data, 'hmac data'), encoding: encoding(enc) }));
163
- },
164
- sign(algorithm, key, data, enc) {
165
- if (algorithm !== 'rsa-sha256')
166
- return Promise.reject(new TypeError(`unsupported sign algorithm ${String(algorithm)}`));
167
- return Promise.resolve().then(() => digest({ op: 'sign', algorithm, key: text(key, 'sign key'), data: text(data, 'sign data'), encoding: encoding(enc) }));
168
- },
169
- hash(algorithm, data, enc) {
170
- if (!HASH_ALGORITHMS.includes(algorithm))
171
- return Promise.reject(new TypeError(`unsupported hash algorithm ${String(algorithm)}`));
172
- return Promise.resolve().then(() => digest({ op: 'hash', algorithm, data: text(data, 'hash data'), encoding: encoding(enc) }));
173
- },
174
- base64Encode,
175
- base64Decode,
176
- });
177
- }
@@ -1,30 +0,0 @@
1
- import type { CheckContext, PullContext } from '../../types.js';
2
- import type { DefinitionSummary } from '../../validate.js';
3
- import type { LogBuffer } from './log.js';
4
- /** 凭证句柄的前缀,与 shared 的 `SECRET_HANDLE_PREFIX` 同值。 */
5
- export declare const SECRET_HANDLE_PREFIX = "ontos:secret:";
6
- export declare function deepFreeze<T>(value: T): T;
7
- /** 相对路径的缺省基址:连接器 `hosts` 里按配置展开后的第一个确定主机(不含 `*`);没有则为 null。 */
8
- export declare function defaultBaseUrl(hosts: readonly string[], config: Record<string, unknown>): string | null;
9
- /**
10
- * `ctx.secrets`:每个已配置的凭证字段给句柄 `ontos:secret:<字段>`;声明了 `exposeToScript` 的字段经 `secret.reveal`
11
- * 取明文。`ctx.secrets` 是同步读取的普通对象,所以这些字段在作业开始前各取一次,缓存到本次运行结束。
12
- */
13
- export declare function prepareSecrets(summary: DefinitionSummary, secretFields: readonly string[]): Promise<Readonly<Record<string, string>>>;
14
- export interface ContextOptions {
15
- config: Record<string, unknown>;
16
- secrets: Readonly<Record<string, string>>;
17
- summary: DefinitionSummary;
18
- logs: LogBuffer;
19
- /** 宿主在 `definition` 回复里给出的生效并发(连接覆盖与连接器声明取小);没给时为 null,只按声明。 */
20
- effectiveConcurrency?: number | null;
21
- }
22
- /**
23
- * `definition` 宿主调用的回复里取生效并发:`{ rateLimit: { concurrency } }`。
24
- * 网关按「连接器声明与连接覆盖取小」限流,`ctx.map` 的上限要跟它一致,否则覆盖更小时会一直撞 429。
25
- * 回复为空(204)或不带这一项时返回 null。
26
- */
27
- export declare function concurrencyFromDefinitionReply(reply: unknown): number | null;
28
- export declare function createCheckContext(options: ContextOptions): CheckContext;
29
- /** 拉取的 `ctx`:`record` / `remove` / `checkpoint` 只产出标记,没有副作用;只有 `yield` 出来的标记算数。 */
30
- export declare function createPullContext(options: ContextOptions): PullContext;
@@ -1,124 +0,0 @@
1
- import { errors } from '../../errors.js';
2
- import { call } from './bridge.js';
3
- import { createCache } from './cache.js';
4
- import { createCrypto } from './crypto.js';
5
- import { createDb } from './db.js';
6
- import { createHttp } from './http.js';
7
- import { DEFAULT_CONCURRENCY } from './limits.js';
8
- import { createMap } from './map.js';
9
- import { createPaginate } from './paginate.js';
10
- import { createSignal } from './signal.js';
11
- import { createTime } from './time.js';
12
- export const SECRET_HANDLE_PREFIX = 'ontos:secret:';
13
- const HOST_PLACEHOLDER = /\{config\.([^{}]*)\}/g;
14
- function isRecord(value) {
15
- return typeof value === 'object' && value !== null && !Array.isArray(value);
16
- }
17
- export function deepFreeze(value) {
18
- if (value === null || typeof value !== 'object')
19
- return value;
20
- for (const key of Object.keys(value))
21
- deepFreeze(value[key]);
22
- return Object.freeze(value);
23
- }
24
- function configString(config, path) {
25
- let current = config;
26
- for (const segment of path.split('.')) {
27
- if (!isRecord(current) || !Object.hasOwn(current, segment))
28
- return undefined;
29
- current = current[segment];
30
- }
31
- return typeof current === 'string' && current.length > 0 ? current : undefined;
32
- }
33
- export function defaultBaseUrl(hosts, config) {
34
- for (const host of hosts) {
35
- let missing = false;
36
- const expanded = host.replace(HOST_PLACEHOLDER, (_match, path) => {
37
- const value = configString(config, path);
38
- if (value === undefined)
39
- missing = true;
40
- return value ?? '';
41
- });
42
- if (!missing && !expanded.includes('*'))
43
- return `https://${expanded}`;
44
- }
45
- return null;
46
- }
47
- export async function prepareSecrets(summary, secretFields) {
48
- const secrets = {};
49
- for (const field of secretFields) {
50
- if (!summary.secretFields.includes(field))
51
- continue;
52
- if (summary.exposeToScript.includes(field)) {
53
- const response = await call('secret.reveal', { field });
54
- if (!isRecord(response) || typeof response.value !== 'string')
55
- throw new TypeError(`secret.reveal returned no value for ${field}`);
56
- secrets[field] = response.value;
57
- }
58
- else {
59
- secrets[field] = `${SECRET_HANDLE_PREFIX}${field}`;
60
- }
61
- }
62
- return Object.freeze(secrets);
63
- }
64
- export function concurrencyFromDefinitionReply(reply) {
65
- if (!isRecord(reply) || !isRecord(reply.rateLimit))
66
- return null;
67
- const concurrency = reply.rateLimit.concurrency;
68
- if (typeof concurrency !== 'number' || !Number.isFinite(concurrency) || concurrency < 1)
69
- return null;
70
- return Math.floor(concurrency);
71
- }
72
- function mapConcurrency(options) {
73
- const declared = options.summary.rateLimit?.concurrency ?? DEFAULT_CONCURRENCY;
74
- const effective = options.effectiveConcurrency ?? null;
75
- return effective === null ? declared : Math.min(declared, effective);
76
- }
77
- function tableName(table) {
78
- if (typeof table !== 'string' || table.length === 0)
79
- throw new TypeError('table must be a non-empty string');
80
- return table;
81
- }
82
- function plainObject(value, what) {
83
- if (!isRecord(value))
84
- throw new TypeError(`${what} must be an object`);
85
- return value;
86
- }
87
- export function createCheckContext(options) {
88
- const config = deepFreeze(options.config);
89
- const http = createHttp(defaultBaseUrl(options.summary.hosts, config));
90
- const ctx = {
91
- config,
92
- secrets: options.secrets,
93
- http,
94
- paginate: createPaginate(http),
95
- db: createDb(),
96
- map: createMap(mapConcurrency(options)),
97
- cache: createCache(),
98
- crypto: createCrypto(),
99
- time: createTime(),
100
- log: options.logs.logger(),
101
- signal: createSignal(),
102
- };
103
- Object.defineProperty(ctx, 'files', {
104
- get() {
105
- throw new errors.NotAvailable('ctx.files');
106
- },
107
- });
108
- return Object.freeze(ctx);
109
- }
110
- export function createPullContext(options) {
111
- const base = createCheckContext(options);
112
- const ctx = Object.create(null);
113
- for (const key of Object.keys(base))
114
- ctx[key] = base[key];
115
- Object.defineProperty(ctx, 'files', {
116
- get() {
117
- throw new errors.NotAvailable('ctx.files');
118
- },
119
- });
120
- ctx.record = (table, row) => Object.freeze({ __ontos: 'record', table: tableName(table), row: plainObject(row, 'row') });
121
- ctx.remove = (table, key) => Object.freeze({ __ontos: 'remove', table: tableName(table), key: plainObject(key, 'key') });
122
- ctx.checkpoint = (state) => Object.freeze({ __ontos: 'checkpoint', state });
123
- return Object.freeze(ctx);
124
- }
@@ -1,6 +0,0 @@
1
- /**
2
- * `ctx.db`:经宿主的数据库代理执行只读查询。`db.query` 回第一批行与游标,未完时逐批 `db.next`;
3
- * 迭代中途退出(`break` / 抛错)时发 `db.close` 释放游标。参数在这里规整成 JSON 值(日期转 ISO 文本,bigint 转字符串)。
4
- */
5
- import type { ConnectorDb } from '../../types.js';
6
- export declare function createDb(): ConnectorDb;
@@ -1,59 +0,0 @@
1
- import { call, isAborted, throwIfAborted } from './bridge.js';
2
- function isRecord(value) {
3
- return typeof value === 'object' && value !== null && !Array.isArray(value);
4
- }
5
- function param(value) {
6
- if (value === undefined)
7
- return null;
8
- if (typeof value === 'bigint')
9
- return value.toString();
10
- if (value instanceof Date)
11
- return value.toISOString();
12
- return value;
13
- }
14
- function rowsOf(value) {
15
- if (!isRecord(value) || !Array.isArray(value.rows) || typeof value.done !== 'boolean')
16
- throw new TypeError('db host call returned a malformed response');
17
- return value.rows;
18
- }
19
- async function* run(sql, params) {
20
- throwIfAborted();
21
- const first = await call('db.query', { sql, params: params.map(param) });
22
- let rows = rowsOf(first);
23
- let done = first.done;
24
- const cursorId = typeof first.cursorId === 'string' ? first.cursorId : null;
25
- if (!done && cursorId === null)
26
- throw new TypeError('db host call returned more rows without a cursor');
27
- try {
28
- for (;;) {
29
- for (const row of rows)
30
- yield row;
31
- if (done || cursorId === null)
32
- return;
33
- throwIfAborted();
34
- const next = await call('db.next', { cursorId });
35
- rows = rowsOf(next);
36
- done = next.done;
37
- }
38
- }
39
- finally {
40
- if (!done && cursorId !== null) {
41
- const closing = call('db.close', { cursorId });
42
- if (isAborted())
43
- closing.catch(() => undefined);
44
- else
45
- await closing;
46
- }
47
- }
48
- }
49
- export function createDb() {
50
- return Object.freeze({
51
- query(sql, params = []) {
52
- if (typeof sql !== 'string' || sql.trim().length === 0)
53
- throw new TypeError('ctx.db.query expects a SQL string');
54
- if (!Array.isArray(params))
55
- throw new TypeError('ctx.db.query params must be an array');
56
- return run(sql, [...params]);
57
- },
58
- });
59
- }
@@ -1,29 +0,0 @@
1
- /**
2
- * discover 与 check 作业:
3
- * - discover:有 `check` 时先跑 `check`,再跑 `discover`;结果经 `validateDiscoverResult` 校验后规整
4
- * (缺省 `snapshot: 'partial'`,推送按名字),连同定义摘要一起回报。`discoverFirst` 的拉取作业复用同一段(`discoverDeclaration`)。
5
- * - check:只跑 `check`(没有时直接成功),结果 `{ kind: 'check', ok: true, logs }`。
6
- */
7
- import type { ConnectorDefinition } from '../../types.js';
8
- import { type DefinitionSummary, type NormalizedDiscoverResult } from '../../validate.js';
9
- import type { GuestResult } from '../protocol.js';
10
- import { type ContextOptions } from './ctx.js';
11
- import { type FailureMessage } from './failure.js';
12
- /** 跑 check(若有)+ discover,返回规整后的声明;连接器出错或结果不合法时返回失败回报。 */
13
- export declare function discoverDeclaration(definition: ConnectorDefinition, options: ContextOptions): Promise<{
14
- ok: true;
15
- discover: NormalizedDiscoverResult;
16
- } | {
17
- ok: false;
18
- failure: FailureMessage;
19
- }>;
20
- export declare function runDiscover(definition: ConnectorDefinition, options: ContextOptions & {
21
- summary: DefinitionSummary;
22
- }): Promise<{
23
- type: 'result';
24
- result: GuestResult;
25
- } | FailureMessage>;
26
- export declare function runCheck(definition: ConnectorDefinition, options: ContextOptions): Promise<{
27
- type: 'result';
28
- result: GuestResult;
29
- } | FailureMessage>;
@@ -1,51 +0,0 @@
1
- import { normalizeDiscoverResult, validateDiscoverResult } from '../../validate.js';
2
- import { jsonParse, jsonStringify, throwIfAborted } from './bridge.js';
3
- import { createCheckContext } from './ctx.js';
4
- import { failure, failureFromError } from './failure.js';
5
- function plain(value) {
6
- const text = jsonStringify(value);
7
- if (typeof text !== 'string')
8
- throw new TypeError('discover result is not serializable');
9
- return jsonParse(text);
10
- }
11
- export async function discoverDeclaration(definition, options) {
12
- const ctx = createCheckContext(options);
13
- let raw;
14
- try {
15
- if (typeof definition.check === 'function')
16
- await Reflect.apply(definition.check, definition, [ctx]);
17
- throwIfAborted();
18
- raw = plain(await Reflect.apply(definition.discover, definition, [ctx]));
19
- throwIfAborted();
20
- }
21
- catch (error) {
22
- return { ok: false, failure: failureFromError(error, options.logs.drain()) };
23
- }
24
- const issues = validateDiscoverResult(raw, definition);
25
- if (issues.length > 0) {
26
- const message = `invalid discover result: ${issues.map((issue) => `${issue.path || '(root)'}: ${issue.message}`).join('; ')}`;
27
- return { ok: false, failure: failure('SCHEMA_ERROR', message, options.logs.drain()) };
28
- }
29
- return { ok: true, discover: normalizeDiscoverResult(raw) };
30
- }
31
- export async function runDiscover(definition, options) {
32
- const outcome = await discoverDeclaration(definition, options);
33
- if (!outcome.ok)
34
- return outcome.failure;
35
- return {
36
- type: 'result',
37
- result: { kind: 'discover', summary: options.summary, discover: outcome.discover, logs: options.logs.drain() },
38
- };
39
- }
40
- export async function runCheck(definition, options) {
41
- const ctx = createCheckContext(options);
42
- try {
43
- if (typeof definition.check === 'function')
44
- await Reflect.apply(definition.check, definition, [ctx]);
45
- throwIfAborted();
46
- }
47
- catch (error) {
48
- return failureFromError(error, options.logs.drain());
49
- }
50
- return { type: 'result', result: { kind: 'check', ok: true, logs: options.logs.drain() } };
51
- }
@@ -1,24 +0,0 @@
1
- /** 把连接器抛出的值归成失败回报。错误类别只按 `code` 字段判断(连接器可能抛任意值)。 */
2
- import type { GuestFailureCode, GuestLog } from '../protocol.js';
3
- export interface ErrorInfo {
4
- code: string | null;
5
- message: string;
6
- stack: string | undefined;
7
- }
8
- /** 只取 code / message / stack 三个原始值;读属性抛错或类型不对时按普通异常处理。 */
9
- export declare function errorInfo(error: unknown): ErrorInfo;
10
- /**
11
- * 调用栈只留第一行(错误文案)与连接器代码自己的帧:宿主帧带 runner 的本地路径,guest 运行时的帧对作者没有意义。
12
- * 连接器代码以 `connector.js` 为文件名加载、包装函数与第一行同行,行号直接对应打包产物。
13
- */
14
- export declare function connectorStack(stack: string | undefined): string | undefined;
15
- export interface FailureMessage {
16
- type: 'failure';
17
- code: GuestFailureCode;
18
- message: string;
19
- stack?: string;
20
- logs: GuestLog[];
21
- }
22
- export declare function failure(code: GuestFailureCode, message: string, logs: GuestLog[], stack?: string): FailureMessage;
23
- /** 连接器异常 → 失败回报:认得的 code 原样映射,其余(含宿主调用的错误码)按 FATAL_ERROR,文案带上原 code;运行已取消时一律 CANCELED。 */
24
- export declare function failureFromError(error: unknown, logs: GuestLog[]): FailureMessage;
@@ -1,63 +0,0 @@
1
- import { isAborted } from './bridge.js';
2
- import { CONNECTOR_FILENAME } from './limits.js';
3
- export function errorInfo(error) {
4
- let code = null;
5
- let message = 'connector threw a non-error value';
6
- let stack;
7
- if (error !== null && (typeof error === 'object' || typeof error === 'function')) {
8
- const value = error;
9
- try {
10
- if (typeof value.code === 'string')
11
- code = value.code;
12
- }
13
- catch {
14
- code = null;
15
- }
16
- try {
17
- if (typeof value.message === 'string')
18
- message = value.message;
19
- }
20
- catch { }
21
- try {
22
- if (typeof value.stack === 'string')
23
- stack = value.stack;
24
- }
25
- catch {
26
- stack = undefined;
27
- }
28
- }
29
- else if (typeof error === 'string') {
30
- message = error;
31
- }
32
- return { code, message, stack };
33
- }
34
- export function connectorStack(stack) {
35
- if (stack === undefined)
36
- return undefined;
37
- const lines = stack.split('\n');
38
- const frames = lines.slice(1).filter((line) => line.includes(`${CONNECTOR_FILENAME}:`));
39
- if (frames.length === 0)
40
- return undefined;
41
- return [lines[0] ?? '', ...frames].join('\n');
42
- }
43
- const CODE_MAP = Object.freeze({
44
- AUTH_ERROR: 'AUTH_ERROR',
45
- TRANSIENT_ERROR: 'TRANSIENT_ERROR',
46
- RATE_LIMITED: 'TRANSIENT_ERROR',
47
- SCHEMA_ERROR: 'SCHEMA_ERROR',
48
- FATAL_ERROR: 'FATAL_ERROR',
49
- CANCELED: 'CANCELED',
50
- });
51
- export function failure(code, message, logs, stack) {
52
- return { type: 'failure', code, message, ...(stack !== undefined ? { stack } : {}), logs };
53
- }
54
- export function failureFromError(error, logs) {
55
- const info = errorInfo(error);
56
- const stack = connectorStack(info.stack);
57
- if (isAborted())
58
- return failure('CANCELED', 'run was canceled', logs, stack);
59
- const mapped = info.code !== null && Object.hasOwn(CODE_MAP, info.code) ? CODE_MAP[info.code] : undefined;
60
- if (mapped)
61
- return failure(mapped, info.message, logs, stack);
62
- return failure('FATAL_ERROR', info.code === null ? info.message : `${info.code}: ${info.message}`, logs, stack);
63
- }
@@ -1,4 +0,0 @@
1
- import type { HttpClient } from '../../types.js';
2
- /** 相对路径拼在 `auth.baseUrl` 上;没有时拼在缺省基址(连接器 `hosts` 里第一个确定的主机)上。 */
3
- export declare function resolveUrl(url: string, baseUrl: string | null): string;
4
- export declare function createHttp(defaultBaseUrl: string | null): HttpClient;