@deepexi/datasense-cli 2.0.3 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/connector-child.cjs +350 -0
- package/dist/datasense-connector-3.0.1.tgz +0 -0
- package/dist/ontos.js +11 -1
- package/package.json +8 -6
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
function __accessProp(key) {
|
|
7
|
+
return this[key];
|
|
8
|
+
}
|
|
9
|
+
var __toESMCache_node;
|
|
10
|
+
var __toESMCache_esm;
|
|
11
|
+
var __toESM = (mod, isNodeMode, target) => {
|
|
12
|
+
var canCache = mod != null && typeof mod === "object";
|
|
13
|
+
if (canCache) {
|
|
14
|
+
var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
|
|
15
|
+
var cached = cache.get(mod);
|
|
16
|
+
if (cached)
|
|
17
|
+
return cached;
|
|
18
|
+
}
|
|
19
|
+
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
20
|
+
const to = isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
|
|
21
|
+
if (mod && typeof mod === "object" || typeof mod === "function") {
|
|
22
|
+
for (let key of __getOwnPropNames(mod))
|
|
23
|
+
if (!__hasOwnProp.call(to, key))
|
|
24
|
+
__defProp(to, key, {
|
|
25
|
+
get: __accessProp.bind(mod, key),
|
|
26
|
+
enumerable: true
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
if (canCache)
|
|
30
|
+
cache.set(mod, to);
|
|
31
|
+
return to;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
// src/runtime/session.ts
|
|
35
|
+
var import_node_vm = __toESM(require("node:vm"), 1);
|
|
36
|
+
|
|
37
|
+
// src/runtime/protocol.ts
|
|
38
|
+
var HOST_METHODS = Object.freeze([
|
|
39
|
+
"definition",
|
|
40
|
+
"declaration",
|
|
41
|
+
"http",
|
|
42
|
+
"db.query",
|
|
43
|
+
"db.next",
|
|
44
|
+
"db.close",
|
|
45
|
+
"crypto",
|
|
46
|
+
"cache.get",
|
|
47
|
+
"cache.set",
|
|
48
|
+
"secret.reveal",
|
|
49
|
+
"emit"
|
|
50
|
+
]);
|
|
51
|
+
var GUEST_FAILURE_CODES = Object.freeze([
|
|
52
|
+
"CONNECTOR_LOAD_FAILED",
|
|
53
|
+
"CONFIG_INVALID",
|
|
54
|
+
"SCHEMA_ERROR",
|
|
55
|
+
"FATAL_ERROR",
|
|
56
|
+
"AUTH_ERROR",
|
|
57
|
+
"TRANSIENT_ERROR",
|
|
58
|
+
"PUSH_UNKNOWN",
|
|
59
|
+
"CANCELED"
|
|
60
|
+
]);
|
|
61
|
+
var HTTP_METHODS = new Set(["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD"]);
|
|
62
|
+
var BODY_ENCODINGS = new Set(["utf8", "base64"]);
|
|
63
|
+
var DIGEST_ENCODINGS = new Set(["hex", "base64"]);
|
|
64
|
+
var HMAC_ALGORITHMS = new Set(["sha1", "sha256", "sha512"]);
|
|
65
|
+
var HASH_ALGORITHMS = new Set(["md5", "sha1", "sha256", "sha512"]);
|
|
66
|
+
var LOG_LEVELS = new Set(["info", "warn", "error"]);
|
|
67
|
+
var SYNC_MODES = new Set(["full", "incremental"]);
|
|
68
|
+
var SNAPSHOTS = new Set(["complete", "partial"]);
|
|
69
|
+
var HOST_METHOD_SET = new Set(HOST_METHODS);
|
|
70
|
+
var FAILURE_CODE_SET = new Set(GUEST_FAILURE_CODES);
|
|
71
|
+
function isRecord(value) {
|
|
72
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
73
|
+
}
|
|
74
|
+
function isStringArray(value) {
|
|
75
|
+
return Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
76
|
+
}
|
|
77
|
+
function isStringRecord(value) {
|
|
78
|
+
return isRecord(value) && Object.values(value).every((item) => typeof item === "string");
|
|
79
|
+
}
|
|
80
|
+
function isId(value) {
|
|
81
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value > 0;
|
|
82
|
+
}
|
|
83
|
+
function parsePushRequest(value) {
|
|
84
|
+
if (!isRecord(value))
|
|
85
|
+
return null;
|
|
86
|
+
const { requestId, push, receivedAt, headers, body } = value;
|
|
87
|
+
if (typeof requestId !== "string" || typeof push !== "string" || typeof receivedAt !== "string" || !isStringRecord(headers) || typeof body !== "string")
|
|
88
|
+
return null;
|
|
89
|
+
return { requestId, push, receivedAt, headers: { ...headers }, body };
|
|
90
|
+
}
|
|
91
|
+
function parseJob(value) {
|
|
92
|
+
if (!isRecord(value) || !isRecord(value.config) || !isStringArray(value.secretFields))
|
|
93
|
+
return null;
|
|
94
|
+
const config = value.config;
|
|
95
|
+
const secretFields = [...value.secretFields];
|
|
96
|
+
if (value.kind === "push") {
|
|
97
|
+
if (!Array.isArray(value.requests))
|
|
98
|
+
return null;
|
|
99
|
+
const requests = [];
|
|
100
|
+
for (const item of value.requests) {
|
|
101
|
+
const request = parsePushRequest(item);
|
|
102
|
+
if (!request)
|
|
103
|
+
return null;
|
|
104
|
+
requests.push(request);
|
|
105
|
+
}
|
|
106
|
+
return { kind: "push", config, secretFields, requests };
|
|
107
|
+
}
|
|
108
|
+
if (value.kind === "discover")
|
|
109
|
+
return { kind: "discover", config, secretFields };
|
|
110
|
+
if (value.kind === "check")
|
|
111
|
+
return { kind: "check", config, secretFields };
|
|
112
|
+
if (value.kind === "pull") {
|
|
113
|
+
const { stream, mode, streamConfig, tables, discoverFirst } = value;
|
|
114
|
+
if (typeof stream !== "string" || typeof mode !== "string" || !SYNC_MODES.has(mode) || !isRecord(streamConfig) || !isStringArray(tables))
|
|
115
|
+
return null;
|
|
116
|
+
if (discoverFirst !== undefined && typeof discoverFirst !== "boolean")
|
|
117
|
+
return null;
|
|
118
|
+
return {
|
|
119
|
+
kind: "pull",
|
|
120
|
+
config,
|
|
121
|
+
secretFields,
|
|
122
|
+
stream,
|
|
123
|
+
mode,
|
|
124
|
+
state: value.state,
|
|
125
|
+
streamConfig,
|
|
126
|
+
tables: [...tables],
|
|
127
|
+
...discoverFirst === true ? { discoverFirst: true } : {}
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
function parseHostError(value) {
|
|
133
|
+
if (!isRecord(value) || typeof value.code !== "string" || typeof value.message !== "string")
|
|
134
|
+
return null;
|
|
135
|
+
const error = { code: value.code, message: value.message };
|
|
136
|
+
if (value.status !== undefined) {
|
|
137
|
+
if (typeof value.status !== "number" || !Number.isInteger(value.status))
|
|
138
|
+
return null;
|
|
139
|
+
error.status = value.status;
|
|
140
|
+
}
|
|
141
|
+
if (value.retryAfterMs !== undefined) {
|
|
142
|
+
if (typeof value.retryAfterMs !== "number" || !Number.isFinite(value.retryAfterMs) || value.retryAfterMs < 0)
|
|
143
|
+
return null;
|
|
144
|
+
error.retryAfterMs = value.retryAfterMs;
|
|
145
|
+
}
|
|
146
|
+
return error;
|
|
147
|
+
}
|
|
148
|
+
function parseParentMessage(value) {
|
|
149
|
+
if (!isRecord(value))
|
|
150
|
+
return null;
|
|
151
|
+
switch (value.type) {
|
|
152
|
+
case "execute": {
|
|
153
|
+
const { guest, code, expect } = value;
|
|
154
|
+
if (typeof guest !== "string" || typeof code !== "string")
|
|
155
|
+
return null;
|
|
156
|
+
if (!isRecord(expect) || typeof expect.name !== "string" || typeof expect.version !== "string")
|
|
157
|
+
return null;
|
|
158
|
+
const job = parseJob(value.job);
|
|
159
|
+
return job ? { type: "execute", guest, code, expect: { name: expect.name, version: expect.version }, job } : null;
|
|
160
|
+
}
|
|
161
|
+
case "reply": {
|
|
162
|
+
if (!isId(value.id))
|
|
163
|
+
return null;
|
|
164
|
+
if (value.ok === true)
|
|
165
|
+
return { type: "reply", id: value.id, ok: true, value: value.value };
|
|
166
|
+
if (value.ok !== false)
|
|
167
|
+
return null;
|
|
168
|
+
const error = parseHostError(value.error);
|
|
169
|
+
return error ? { type: "reply", id: value.id, ok: false, error } : null;
|
|
170
|
+
}
|
|
171
|
+
case "cancel":
|
|
172
|
+
return { type: "cancel" };
|
|
173
|
+
default:
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// src/runtime/session.ts
|
|
179
|
+
var GUEST_FILENAME = "ontos-guest.js";
|
|
180
|
+
var CONNECTOR_FILENAME = "connector.js";
|
|
181
|
+
function isRecord2(value) {
|
|
182
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
183
|
+
}
|
|
184
|
+
function guestErrorMessage(error) {
|
|
185
|
+
try {
|
|
186
|
+
if (error !== null && typeof error === "object") {
|
|
187
|
+
const message = error.message;
|
|
188
|
+
if (typeof message === "string")
|
|
189
|
+
return message;
|
|
190
|
+
}
|
|
191
|
+
} catch {}
|
|
192
|
+
return "unknown error";
|
|
193
|
+
}
|
|
194
|
+
function bootGuest(context, guestSource) {
|
|
195
|
+
const wrapped = `(() => { const module = { exports: {} }; const exports = module.exports; ${guestSource}
|
|
196
|
+
; return module.exports; })()`;
|
|
197
|
+
const exported = new import_node_vm.default.Script(wrapped, { filename: GUEST_FILENAME }).runInContext(context);
|
|
198
|
+
const boot = exported.bootGuest;
|
|
199
|
+
if (typeof boot !== "function")
|
|
200
|
+
throw new Error("guest runtime does not export bootGuest");
|
|
201
|
+
const api = boot();
|
|
202
|
+
const { start, handle, poll } = api;
|
|
203
|
+
if (typeof start !== "function" || typeof handle !== "function" || typeof poll !== "function")
|
|
204
|
+
throw new Error("guest runtime returned an incomplete API");
|
|
205
|
+
return { start, handle, poll };
|
|
206
|
+
}
|
|
207
|
+
function bootInVm(guestSource, code) {
|
|
208
|
+
const context = import_node_vm.default.createContext(Object.create(null), { codeGeneration: { strings: false, wasm: false } });
|
|
209
|
+
let guest;
|
|
210
|
+
try {
|
|
211
|
+
guest = bootGuest(context, guestSource);
|
|
212
|
+
} catch (error) {
|
|
213
|
+
return { ok: false, code: "CONNECTOR_LOAD_FAILED", message: `connector runtime failed to start: ${guestErrorMessage(error)}` };
|
|
214
|
+
}
|
|
215
|
+
try {
|
|
216
|
+
const factory = new import_node_vm.default.Script(`(function (module, exports, require) {${code}
|
|
217
|
+
})`, { filename: CONNECTOR_FILENAME }).runInContext(context);
|
|
218
|
+
return { ok: true, guest, factory };
|
|
219
|
+
} catch (error) {
|
|
220
|
+
return { ok: false, code: "CONNECTOR_LOAD_FAILED", message: `connector code failed to compile: ${guestErrorMessage(error)}` };
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
function createGuestSession(send) {
|
|
224
|
+
return createSession(send, bootInVm);
|
|
225
|
+
}
|
|
226
|
+
function createSession(send, boot) {
|
|
227
|
+
let guest = null;
|
|
228
|
+
let started = false;
|
|
229
|
+
let done = false;
|
|
230
|
+
let timer;
|
|
231
|
+
let timerAt = Number.POSITIVE_INFINITY;
|
|
232
|
+
const stop = () => {
|
|
233
|
+
done = true;
|
|
234
|
+
if (timer !== undefined)
|
|
235
|
+
clearTimeout(timer);
|
|
236
|
+
timer = undefined;
|
|
237
|
+
};
|
|
238
|
+
const fail = (code, message) => {
|
|
239
|
+
if (done)
|
|
240
|
+
return;
|
|
241
|
+
stop();
|
|
242
|
+
send(JSON.stringify({ type: "failure", code, message, logs: [] }));
|
|
243
|
+
};
|
|
244
|
+
const schedule = (delay) => {
|
|
245
|
+
if (done)
|
|
246
|
+
return;
|
|
247
|
+
const at = Date.now() + delay;
|
|
248
|
+
if (timer !== undefined && timerAt <= at)
|
|
249
|
+
return;
|
|
250
|
+
if (timer !== undefined)
|
|
251
|
+
clearTimeout(timer);
|
|
252
|
+
timerAt = at;
|
|
253
|
+
timer = setTimeout(pump, delay);
|
|
254
|
+
};
|
|
255
|
+
function pump() {
|
|
256
|
+
timer = undefined;
|
|
257
|
+
timerAt = Number.POSITIVE_INFINITY;
|
|
258
|
+
if (done || !guest)
|
|
259
|
+
return;
|
|
260
|
+
let text;
|
|
261
|
+
try {
|
|
262
|
+
text = guest.poll();
|
|
263
|
+
} catch (error) {
|
|
264
|
+
fail("FATAL_ERROR", `connector runtime failed: ${guestErrorMessage(error)}`);
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
let parsed;
|
|
268
|
+
try {
|
|
269
|
+
parsed = typeof text === "string" ? JSON.parse(text) : null;
|
|
270
|
+
} catch {
|
|
271
|
+
parsed = null;
|
|
272
|
+
}
|
|
273
|
+
if (!isRecord2(parsed) || !Array.isArray(parsed.out)) {
|
|
274
|
+
fail("FATAL_ERROR", "connector runtime returned a malformed poll result");
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
for (const message of parsed.out) {
|
|
278
|
+
if (!isRecord2(message))
|
|
279
|
+
continue;
|
|
280
|
+
send(JSON.stringify(message));
|
|
281
|
+
if (message.type === "result" || message.type === "failure") {
|
|
282
|
+
stop();
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
if (parsed.out.length > 0 || parsed.fired === true)
|
|
287
|
+
schedule(0);
|
|
288
|
+
else if (typeof parsed.wake === "number" && parsed.wake >= 0)
|
|
289
|
+
schedule(parsed.wake);
|
|
290
|
+
}
|
|
291
|
+
const execute = (guestSource, code, payload) => {
|
|
292
|
+
const booted = boot(guestSource, code);
|
|
293
|
+
if (!booted.ok) {
|
|
294
|
+
fail(booted.code, booted.message);
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
guest = booted.guest;
|
|
298
|
+
try {
|
|
299
|
+
guest.start(payload, booted.factory);
|
|
300
|
+
} catch (error) {
|
|
301
|
+
fail("FATAL_ERROR", `connector runtime failed: ${guestErrorMessage(error)}`);
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
schedule(0);
|
|
305
|
+
};
|
|
306
|
+
return {
|
|
307
|
+
handle(json) {
|
|
308
|
+
if (done || typeof json !== "string")
|
|
309
|
+
return;
|
|
310
|
+
let raw;
|
|
311
|
+
try {
|
|
312
|
+
raw = JSON.parse(json);
|
|
313
|
+
} catch {
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
const message = parseParentMessage(raw);
|
|
317
|
+
if (!message)
|
|
318
|
+
return;
|
|
319
|
+
if (message.type === "execute") {
|
|
320
|
+
if (started)
|
|
321
|
+
return;
|
|
322
|
+
started = true;
|
|
323
|
+
execute(message.guest, message.code, JSON.stringify({ expect: message.expect, job: message.job }));
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
if (!guest)
|
|
327
|
+
return;
|
|
328
|
+
try {
|
|
329
|
+
guest.handle(JSON.stringify(message));
|
|
330
|
+
} catch (error) {
|
|
331
|
+
fail("FATAL_ERROR", `connector runtime failed: ${guestErrorMessage(error)}`);
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
schedule(0);
|
|
335
|
+
}
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// src/testing/child.ts
|
|
340
|
+
var session = createGuestSession((json) => {
|
|
341
|
+
process.send?.(json);
|
|
342
|
+
});
|
|
343
|
+
process.on("message", (raw) => {
|
|
344
|
+
if (typeof raw === "string")
|
|
345
|
+
session.handle(raw);
|
|
346
|
+
});
|
|
347
|
+
process.on("disconnect", () => {
|
|
348
|
+
process.exit(0);
|
|
349
|
+
});
|
|
350
|
+
process.send?.(JSON.stringify({ type: "ready" }));
|
|
Binary file
|