@requence/service 0.8.2-edge.1154 → 0.8.2-edge.1156
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 +258 -0
- package/build/{chunk-974rc2jy.js → chunk-gpyt51xn.js} +164 -3
- package/build/{chunk-974rc2jy.js.map → chunk-gpyt51xn.js.map} +7 -4
- package/build/cli.js +17 -30
- package/build/cli.js.map +3 -3
- package/build/index.js +537 -93
- package/build/index.js.map +17 -9
- package/build/types/helpers/src/index.d.ts +4 -0
- package/build/types/helpers/src/index.d.ts.map +1 -1
- package/build/types/helpers/src/protocol/NodeTree.d.ts +20 -0
- package/build/types/helpers/src/protocol/NodeTree.d.ts.map +1 -1
- package/build/types/helpers/src/protocol/command.d.ts +74 -13
- package/build/types/helpers/src/protocol/command.d.ts.map +1 -1
- package/build/types/helpers/src/protocol/update.d.ts +128 -10
- package/build/types/helpers/src/protocol/update.d.ts.map +1 -1
- package/build/types/helpers/src/utils/matchSchema.d.ts +14 -0
- package/build/types/helpers/src/utils/matchSchema.d.ts.map +1 -1
- package/build/types/helpers/src/utils/serviceRender.d.ts +73 -0
- package/build/types/helpers/src/utils/serviceRender.d.ts.map +1 -0
- package/build/types/helpers/src/utils/surfaceComponent.d.ts +116 -0
- package/build/types/helpers/src/utils/surfaceComponent.d.ts.map +1 -0
- package/build/types/helpers/src/utils/surfaceHandler.d.ts +171 -0
- package/build/types/helpers/src/utils/surfaceHandler.d.ts.map +1 -0
- package/build/types/helpers/src/utils/uiRebuild.d.ts +48 -0
- package/build/types/helpers/src/utils/uiRebuild.d.ts.map +1 -0
- package/build/types/service/src/boundary.d.ts +14 -1
- package/build/types/service/src/boundary.d.ts.map +1 -1
- package/build/types/service/src/createAmqpConnection.d.ts +55 -0
- package/build/types/service/src/createAmqpConnection.d.ts.map +1 -1
- package/build/types/service/src/errors.d.ts +11 -0
- package/build/types/service/src/errors.d.ts.map +1 -1
- package/build/types/service/src/helpers.d.ts +68 -0
- package/build/types/service/src/helpers.d.ts.map +1 -1
- package/build/types/service/src/index.d.ts +2 -0
- package/build/types/service/src/index.d.ts.map +1 -1
- package/build/types/service/src/surfaceHandler.d.ts +36 -0
- package/build/types/service/src/surfaceHandler.d.ts.map +1 -0
- package/build/types/service/src/surfaceUi.d.ts +141 -0
- package/build/types/service/src/surfaceUi.d.ts.map +1 -0
- package/build/types/service/src/transformer.d.ts +14 -0
- package/build/types/service/src/transformer.d.ts.map +1 -1
- package/build/types/service/src/ui.d.ts +247 -0
- package/build/types/service/src/ui.d.ts.map +1 -0
- package/build/types/service/src/uiWatch.d.ts +68 -0
- package/build/types/service/src/uiWatch.d.ts.map +1 -0
- package/package.json +10 -4
package/build/index.js
CHANGED
|
@@ -3,7 +3,10 @@ import {
|
|
|
3
3
|
PayloadTooLargeError,
|
|
4
4
|
RequenceConnectionError,
|
|
5
5
|
RequenceUnreachableError,
|
|
6
|
+
UITooLargeError,
|
|
6
7
|
UnsupportedCapabilityError,
|
|
8
|
+
__commonJS,
|
|
9
|
+
__toESM,
|
|
7
10
|
assertReachable,
|
|
8
11
|
buildServiceClientProperties,
|
|
9
12
|
buildServiceIdentityHeaders,
|
|
@@ -12,11 +15,21 @@ import {
|
|
|
12
15
|
obfuscate,
|
|
13
16
|
reachableFetch,
|
|
14
17
|
readRequiredCapabilities,
|
|
18
|
+
simple_default,
|
|
15
19
|
unsupportedCapabilities
|
|
16
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-gpyt51xn.js";
|
|
21
|
+
|
|
22
|
+
// ../../node_modules/.bun/dlv@1.1.3/node_modules/dlv/dist/dlv.js
|
|
23
|
+
var require_dlv = __commonJS((exports, module) => {
|
|
24
|
+
module.exports = function(t, e, l, n, o) {
|
|
25
|
+
for (e = e.split ? e.split(".") : e, n = 0;n < e.length; n++)
|
|
26
|
+
t = t ? t[e[n]] : o;
|
|
27
|
+
return t === o ? l : t;
|
|
28
|
+
};
|
|
29
|
+
});
|
|
17
30
|
|
|
18
31
|
// src/index.ts
|
|
19
|
-
import
|
|
32
|
+
import fs3 from "node:fs";
|
|
20
33
|
|
|
21
34
|
// ../helpers/src/utils/guards.ts
|
|
22
35
|
import { z } from "zod/v4";
|
|
@@ -188,9 +201,88 @@ function createCallback(callback) {
|
|
|
188
201
|
});
|
|
189
202
|
}
|
|
190
203
|
|
|
204
|
+
// ../helpers/src/utils/serviceRender.ts
|
|
205
|
+
import { z as z6 } from "zod/v4";
|
|
206
|
+
var serviceRenderSchema = z6.object({
|
|
207
|
+
component: z6.object({
|
|
208
|
+
id: z6.string(),
|
|
209
|
+
hash: z6.string(),
|
|
210
|
+
source: z6.string().nullable().default(null)
|
|
211
|
+
}),
|
|
212
|
+
props: z6.unknown(),
|
|
213
|
+
defaults: z6.unknown().optional(),
|
|
214
|
+
surfaceId: z6.string(),
|
|
215
|
+
devSession: z6.string().nullable().default(null)
|
|
216
|
+
});
|
|
217
|
+
var MAX_UI_SOURCE_BYTES = 1024 * 1024;
|
|
218
|
+
var DEFAULT_SURFACE_ID = "default";
|
|
219
|
+
var MAX_SURFACE_INTERACTION_BYTES = 64 * 1024;
|
|
220
|
+
|
|
221
|
+
// ../helpers/src/utils/surfaceHandler.ts
|
|
222
|
+
import { z as z7 } from "zod/v4";
|
|
223
|
+
var SURFACE_HANDLER_TAG = "RequenceHandler";
|
|
224
|
+
var handlerPathSchema = z7.array(z7.union([z7.string(), z7.int()]));
|
|
225
|
+
var surfaceHandlerObjectSchema = z7.discriminatedUnion("lifetime", [
|
|
226
|
+
z7.object({
|
|
227
|
+
__REQUENCE_type: z7.literal(SURFACE_HANDLER_TAG),
|
|
228
|
+
lifetime: z7.literal("durable"),
|
|
229
|
+
uiId: z7.string(),
|
|
230
|
+
path: handlerPathSchema
|
|
231
|
+
}),
|
|
232
|
+
z7.object({
|
|
233
|
+
__REQUENCE_type: z7.literal(SURFACE_HANDLER_TAG),
|
|
234
|
+
lifetime: z7.literal("connection"),
|
|
235
|
+
uiId: z7.string(),
|
|
236
|
+
path: handlerPathSchema,
|
|
237
|
+
connectionId: z7.string(),
|
|
238
|
+
handlerId: z7.uuid()
|
|
239
|
+
})
|
|
240
|
+
]);
|
|
241
|
+
function isSurfaceHandlerObject(data) {
|
|
242
|
+
return surfaceHandlerObjectSchema.safeParse(data).success;
|
|
243
|
+
}
|
|
244
|
+
function serviceHandlerQueueName(dispatchQueue) {
|
|
245
|
+
return `${dispatchQueue}-handlers`;
|
|
246
|
+
}
|
|
247
|
+
var SURFACE_HANDLER_INVOCATION_TTL_MS = 60000;
|
|
248
|
+
var SURFACE_HANDLER_QUEUE_ARGUMENTS = {
|
|
249
|
+
messageTtl: SURFACE_HANDLER_INVOCATION_TTL_MS,
|
|
250
|
+
deadLetterExchange: "error"
|
|
251
|
+
};
|
|
252
|
+
var surfaceHandlerInvocationSchema = z7.object({
|
|
253
|
+
taskId: z7.uuid(),
|
|
254
|
+
surface: z7.uuid(),
|
|
255
|
+
uiId: z7.string(),
|
|
256
|
+
path: handlerPathSchema,
|
|
257
|
+
arg: z7.unknown().optional()
|
|
258
|
+
});
|
|
259
|
+
var MAX_SURFACE_INTERACTION_ERROR_CHARS = 500;
|
|
260
|
+
var SURFACE_INTERACTION_ERROR_HEADER = "surfaceInteractionError";
|
|
261
|
+
var surfaceInteractionErrorReportSchema = z7.object({
|
|
262
|
+
surface: z7.uuid(),
|
|
263
|
+
message: z7.string()
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
// ../helpers/src/utils/uiRebuild.ts
|
|
267
|
+
import { z as z8 } from "zod/v4";
|
|
268
|
+
var UI_REBUILD_HEADER = "uiRebuild";
|
|
269
|
+
var uiRebuildSchema = z8.object({
|
|
270
|
+
devSession: z8.string(),
|
|
271
|
+
uiId: z8.string(),
|
|
272
|
+
hash: z8.string(),
|
|
273
|
+
source: z8.string()
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
// ../helpers/src/utils/obj.ts
|
|
277
|
+
var import_dlv = __toESM(require_dlv(), 1);
|
|
278
|
+
var getByPath = import_dlv.default;
|
|
279
|
+
|
|
191
280
|
// ../helpers/src/utils/amqpHeartbeat.ts
|
|
192
281
|
var DEFAULT_AMQP_HEARTBEAT_SECONDS = 30;
|
|
193
282
|
|
|
283
|
+
// src/createAmqpConnection.ts
|
|
284
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
285
|
+
|
|
194
286
|
// ../helpers/src/msgpack/index.ts
|
|
195
287
|
import { Buffer as Buffer2 } from "node:buffer";
|
|
196
288
|
import { Packr, addExtension } from "msgpackr";
|
|
@@ -257,7 +349,7 @@ function wireBodyByteLength(value, codec) {
|
|
|
257
349
|
|
|
258
350
|
// src/createAmqpConnection.ts
|
|
259
351
|
import { connect } from "amqp-connection-manager";
|
|
260
|
-
import { z as
|
|
352
|
+
import { z as z9 } from "zod/v4";
|
|
261
353
|
|
|
262
354
|
// ../files/src/errors.ts
|
|
263
355
|
class RequenceStreamTruncatedError extends Error {
|
|
@@ -832,7 +924,7 @@ function createMessageHandler() {
|
|
|
832
924
|
}
|
|
833
925
|
return offload(ctx, uploadUrl, json);
|
|
834
926
|
}
|
|
835
|
-
const entries = Object.entries(body).map(([key, value]) => ({
|
|
927
|
+
const entries = Object.entries(body).filter(([key]) => !ctx.inlineKeys?.includes(key)).map(([key, value]) => ({
|
|
836
928
|
key,
|
|
837
929
|
valueJson: toOffloadJson(value),
|
|
838
930
|
size: measure(value)
|
|
@@ -1091,8 +1183,25 @@ function assertTopLevelKeysPreserved(body, wrapped, handlerIndex) {
|
|
|
1091
1183
|
throw new TransformError(`${label} changed a record body's top-level keys (removed: [${removed.join(", ")}], added: [${added.join(", ")}]) — wrapOutbound must preserve them`, []);
|
|
1092
1184
|
}
|
|
1093
1185
|
}
|
|
1186
|
+
// src/surfaceHandler.ts
|
|
1187
|
+
function createSurfaceHandlerValueHandler() {
|
|
1188
|
+
return {
|
|
1189
|
+
tag: SURFACE_HANDLER_TAG,
|
|
1190
|
+
canHandle: (value) => typeof value === "function",
|
|
1191
|
+
serialize(handler, ctx, path) {
|
|
1192
|
+
return ctx.onSurfaceHandler(handler, path);
|
|
1193
|
+
},
|
|
1194
|
+
isReference: (value) => isSurfaceHandlerObject(value),
|
|
1195
|
+
deserialize() {
|
|
1196
|
+
throw new Error("a surface handler reference is outbound-only — it is invoked by its own message, never reconstructed");
|
|
1197
|
+
}
|
|
1198
|
+
};
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1094
1201
|
// src/transformer.ts
|
|
1095
|
-
var
|
|
1202
|
+
var byteReferences = createTransformer().withHandler(createRequenceFileHandler()).withHandler(createRequenceStreamHandler());
|
|
1203
|
+
var transformer = byteReferences.withHandler(createRequenceCallbackHandler()).withHandler(createClaimCheckHandler());
|
|
1204
|
+
var renderTransformer = byteReferences.withHandler(createSurfaceHandlerValueHandler()).withHandler(createClaimCheckHandler());
|
|
1096
1205
|
var passthroughHandler = (handler) => ({
|
|
1097
1206
|
tag: handler.tag,
|
|
1098
1207
|
passthrough: true,
|
|
@@ -1109,7 +1218,7 @@ var passthroughInboundTransformer = createTransformer().withHandler(passthroughH
|
|
|
1109
1218
|
|
|
1110
1219
|
// src/boundary.ts
|
|
1111
1220
|
function createOutboundBoundary(base) {
|
|
1112
|
-
const warn = base.warn ?? ((message, error) => error === undefined ?
|
|
1221
|
+
const warn = base.warn ?? ((message, error) => error === undefined ? simple_default.warn(message) : simple_default.warn(message, error));
|
|
1113
1222
|
const ledger = [];
|
|
1114
1223
|
const errors = [];
|
|
1115
1224
|
const codec = base.wireCodec ?? "json";
|
|
@@ -1132,6 +1241,7 @@ function createOutboundBoundary(base) {
|
|
|
1132
1241
|
measure,
|
|
1133
1242
|
outputName: opts.outputName ?? null,
|
|
1134
1243
|
onCallback: opts.onCallback,
|
|
1244
|
+
inlineKeys: opts.inlineKeys,
|
|
1135
1245
|
...opts.bestEffort ? {
|
|
1136
1246
|
onOffloadFail: (error) => warn("offload failed (best-effort log path):", error),
|
|
1137
1247
|
onOffloadSkip: () => warn("offload skipped: no upload transport configured")
|
|
@@ -1147,7 +1257,10 @@ function createOutboundBoundary(base) {
|
|
|
1147
1257
|
return;
|
|
1148
1258
|
}
|
|
1149
1259
|
}
|
|
1150
|
-
const { value, done } = await withRequenceStreams(() =>
|
|
1260
|
+
const { value, done } = await withRequenceStreams(() => opts.onSurfaceHandler ? renderTransformer.outbound(data, {
|
|
1261
|
+
...ctx,
|
|
1262
|
+
onSurfaceHandler: opts.onSurfaceHandler
|
|
1263
|
+
}) : transformer.outbound(data, ctx));
|
|
1151
1264
|
track(done);
|
|
1152
1265
|
return value;
|
|
1153
1266
|
},
|
|
@@ -1234,6 +1347,13 @@ async function createContextHelper(options) {
|
|
|
1234
1347
|
};
|
|
1235
1348
|
},
|
|
1236
1349
|
defer: options.onDefer,
|
|
1350
|
+
render(ui, props, renderOptions) {
|
|
1351
|
+
options.onRender({
|
|
1352
|
+
ui,
|
|
1353
|
+
props,
|
|
1354
|
+
surfaceId: renderOptions?.surfaceId ?? DEFAULT_SURFACE_ID
|
|
1355
|
+
});
|
|
1356
|
+
},
|
|
1237
1357
|
debug: {
|
|
1238
1358
|
log(...data) {
|
|
1239
1359
|
options.onLog("log", data);
|
|
@@ -1264,8 +1384,105 @@ async function createContextHelper(options) {
|
|
|
1264
1384
|
}
|
|
1265
1385
|
var handlerStorage = new AsyncLocalStorage2;
|
|
1266
1386
|
|
|
1387
|
+
// src/uiWatch.ts
|
|
1388
|
+
import { createHash } from "node:crypto";
|
|
1389
|
+
import fs from "node:fs";
|
|
1390
|
+
import path from "node:path";
|
|
1391
|
+
var REBUILD_DEBOUNCE_MS = 100;
|
|
1392
|
+
var registrations = new Set;
|
|
1393
|
+
var listeners = new Set;
|
|
1394
|
+
var watching = false;
|
|
1395
|
+
function warn(message) {
|
|
1396
|
+
listeners.forEach((listener) => listener.onWarning(message));
|
|
1397
|
+
}
|
|
1398
|
+
function registerUI(ui, filePath) {
|
|
1399
|
+
const clash = [...registrations].find((existing) => existing.ui.id === ui.id);
|
|
1400
|
+
if (clash) {
|
|
1401
|
+
throw new Error(`two components share the UI id "${ui.id}" (${clash.path} and ${filePath}) — pass an explicit id: createUI({ url, id: '…' })`);
|
|
1402
|
+
}
|
|
1403
|
+
const registration = { ui, path: filePath };
|
|
1404
|
+
registrations.add(registration);
|
|
1405
|
+
if (watching) {
|
|
1406
|
+
startWatching(registration);
|
|
1407
|
+
}
|
|
1408
|
+
}
|
|
1409
|
+
function findUIById(id) {
|
|
1410
|
+
return [...registrations].find((entry) => entry.ui.id === id)?.ui;
|
|
1411
|
+
}
|
|
1412
|
+
function watchUIRebuilds(listener) {
|
|
1413
|
+
listeners.add(listener);
|
|
1414
|
+
if (!watching) {
|
|
1415
|
+
watching = true;
|
|
1416
|
+
registrations.forEach(startWatching);
|
|
1417
|
+
}
|
|
1418
|
+
return () => {
|
|
1419
|
+
listeners.delete(listener);
|
|
1420
|
+
if (listeners.size > 0) {
|
|
1421
|
+
return;
|
|
1422
|
+
}
|
|
1423
|
+
watching = false;
|
|
1424
|
+
for (const registration of registrations) {
|
|
1425
|
+
registration.stop?.();
|
|
1426
|
+
registration.stop = undefined;
|
|
1427
|
+
}
|
|
1428
|
+
};
|
|
1429
|
+
}
|
|
1430
|
+
function startWatching(registration) {
|
|
1431
|
+
if (registration.stop) {
|
|
1432
|
+
return;
|
|
1433
|
+
}
|
|
1434
|
+
const directory = path.dirname(registration.path);
|
|
1435
|
+
let timer;
|
|
1436
|
+
let watcher;
|
|
1437
|
+
try {
|
|
1438
|
+
watcher = fs.watch(directory, () => {
|
|
1439
|
+
clearTimeout(timer);
|
|
1440
|
+
timer = setTimeout(() => reload(registration), REBUILD_DEBOUNCE_MS);
|
|
1441
|
+
timer.unref?.();
|
|
1442
|
+
});
|
|
1443
|
+
} catch (error) {
|
|
1444
|
+
warn(`Requence: cannot watch ${registration.path} for rebuilds: ${error instanceof Error ? error.message : String(error)}`);
|
|
1445
|
+
return;
|
|
1446
|
+
}
|
|
1447
|
+
watcher.unref?.();
|
|
1448
|
+
watcher.on("error", (error) => {
|
|
1449
|
+
warn(`Requence: stopped watching ${registration.path}: ${error.message}`);
|
|
1450
|
+
});
|
|
1451
|
+
registration.stop = () => {
|
|
1452
|
+
clearTimeout(timer);
|
|
1453
|
+
watcher.close();
|
|
1454
|
+
};
|
|
1455
|
+
}
|
|
1456
|
+
function reload(registration) {
|
|
1457
|
+
let bundle;
|
|
1458
|
+
try {
|
|
1459
|
+
bundle = fs.readFileSync(registration.path);
|
|
1460
|
+
} catch {
|
|
1461
|
+
return;
|
|
1462
|
+
}
|
|
1463
|
+
const hash = createHash("sha256").update(bundle).digest("hex");
|
|
1464
|
+
if (hash === registration.ui.hash) {
|
|
1465
|
+
return;
|
|
1466
|
+
}
|
|
1467
|
+
if (bundle.byteLength > MAX_UI_SOURCE_BYTES) {
|
|
1468
|
+
if (hash !== registration.refusedHash) {
|
|
1469
|
+
registration.refusedHash = hash;
|
|
1470
|
+
warn(`Requence: rebuilt component ${registration.path} is ${bundle.byteLength} bytes, over the ${MAX_UI_SOURCE_BYTES} limit — keeping the previous bundle`);
|
|
1471
|
+
}
|
|
1472
|
+
return;
|
|
1473
|
+
}
|
|
1474
|
+
registration.ui.hash = hash;
|
|
1475
|
+
registration.ui.source = bundle.toString("utf-8");
|
|
1476
|
+
for (const listener of [...listeners]) {
|
|
1477
|
+
listener.onRebuild(registration.ui);
|
|
1478
|
+
}
|
|
1479
|
+
}
|
|
1480
|
+
|
|
1267
1481
|
// src/createAmqpConnection.ts
|
|
1268
|
-
|
|
1482
|
+
function errorText(error) {
|
|
1483
|
+
return error instanceof Error ? error.message : String(error);
|
|
1484
|
+
}
|
|
1485
|
+
var messageKeySchema = z9.string().transform((str) => deobfuscate(str)).pipe(z9.tuple([z9.uuid(), z9.uuid()]).rest(z9.string())).transform((arr) => ({
|
|
1269
1486
|
taskId: arr[0],
|
|
1270
1487
|
messageId: arr[1],
|
|
1271
1488
|
uploadUrl: arr[2] || undefined,
|
|
@@ -1273,12 +1490,12 @@ var messageKeySchema = z6.string().transform((str) => deobfuscate(str)).pipe(z6.
|
|
|
1273
1490
|
maxPayloadSize: arr[4] && Number.isFinite(Number(arr[4])) ? Number(arr[4]) : undefined,
|
|
1274
1491
|
maxFileSize: arr[5] && Number.isFinite(Number(arr[5])) ? Number(arr[5]) : undefined
|
|
1275
1492
|
}));
|
|
1276
|
-
var headerSchema =
|
|
1277
|
-
properties:
|
|
1278
|
-
correlationId:
|
|
1279
|
-
headers:
|
|
1280
|
-
taskId:
|
|
1281
|
-
mode:
|
|
1493
|
+
var headerSchema = z9.object({
|
|
1494
|
+
properties: z9.object({
|
|
1495
|
+
correlationId: z9.uuid(),
|
|
1496
|
+
headers: z9.object({
|
|
1497
|
+
taskId: z9.uuid(),
|
|
1498
|
+
mode: z9.enum(["LINEAR", "CONTINUOUS"]).default("LINEAR")
|
|
1282
1499
|
})
|
|
1283
1500
|
})
|
|
1284
1501
|
}).transform((msg) => ({
|
|
@@ -1286,62 +1503,66 @@ var headerSchema = z6.object({
|
|
|
1286
1503
|
taskId: msg.properties.headers.taskId,
|
|
1287
1504
|
mode: msg.properties.headers.mode
|
|
1288
1505
|
}));
|
|
1289
|
-
var payloadSchema =
|
|
1290
|
-
content:
|
|
1291
|
-
properties:
|
|
1292
|
-
}).transform((msg) => decodeWireBody(msg.content, msg.properties.contentType)).pipe(
|
|
1293
|
-
input:
|
|
1294
|
-
configuration:
|
|
1295
|
-
options:
|
|
1296
|
-
uploadUrl:
|
|
1297
|
-
streamUrl:
|
|
1298
|
-
maxPayloadSize:
|
|
1299
|
-
maxFileSize:
|
|
1506
|
+
var payloadSchema = z9.object({
|
|
1507
|
+
content: z9.instanceof(Buffer),
|
|
1508
|
+
properties: z9.object({ contentType: z9.string().optional() })
|
|
1509
|
+
}).transform((msg) => decodeWireBody(msg.content, msg.properties.contentType)).pipe(z9.object({
|
|
1510
|
+
input: z9.unknown().optional(),
|
|
1511
|
+
configuration: z9.unknown().optional(),
|
|
1512
|
+
options: z9.object({
|
|
1513
|
+
uploadUrl: z9.url().optional(),
|
|
1514
|
+
streamUrl: z9.url().optional(),
|
|
1515
|
+
maxPayloadSize: z9.number().optional(),
|
|
1516
|
+
maxFileSize: z9.number().optional()
|
|
1300
1517
|
})
|
|
1301
1518
|
}));
|
|
1302
|
-
var backchannelMessageSchema =
|
|
1303
|
-
content:
|
|
1304
|
-
properties:
|
|
1305
|
-
correlationId:
|
|
1306
|
-
contentType:
|
|
1519
|
+
var backchannelMessageSchema = z9.object({
|
|
1520
|
+
content: z9.instanceof(Buffer),
|
|
1521
|
+
properties: z9.object({
|
|
1522
|
+
correlationId: z9.string(),
|
|
1523
|
+
contentType: z9.string().optional(),
|
|
1524
|
+
headers: z9.object({ taskId: z9.uuid().optional() }).optional().catch(undefined)
|
|
1307
1525
|
})
|
|
1308
1526
|
}).transform((message) => ({
|
|
1309
1527
|
...message,
|
|
1310
1528
|
content: decodeWireBody(message.content, message.properties.contentType)
|
|
1311
|
-
})).pipe(
|
|
1312
|
-
content:
|
|
1313
|
-
|
|
1314
|
-
type:
|
|
1529
|
+
})).pipe(z9.object({
|
|
1530
|
+
content: z9.discriminatedUnion("type", [
|
|
1531
|
+
z9.object({
|
|
1532
|
+
type: z9.literal("stop")
|
|
1315
1533
|
}),
|
|
1316
|
-
|
|
1317
|
-
type:
|
|
1318
|
-
callbackId:
|
|
1319
|
-
arg:
|
|
1534
|
+
z9.object({
|
|
1535
|
+
type: z9.literal("callback"),
|
|
1536
|
+
callbackId: z9.uuid(),
|
|
1537
|
+
arg: z9.any().optional(),
|
|
1538
|
+
surface: z9.uuid().optional()
|
|
1320
1539
|
})
|
|
1321
1540
|
]),
|
|
1322
|
-
properties:
|
|
1323
|
-
correlationId:
|
|
1541
|
+
properties: z9.object({
|
|
1542
|
+
correlationId: z9.string(),
|
|
1543
|
+
headers: z9.object({ taskId: z9.uuid().optional() }).optional().catch(undefined)
|
|
1324
1544
|
})
|
|
1325
1545
|
})).transform((message) => ({
|
|
1326
1546
|
payload: message.content,
|
|
1327
|
-
messageId: message.properties.correlationId
|
|
1547
|
+
messageId: message.properties.correlationId,
|
|
1548
|
+
taskId: message.properties.headers?.taskId
|
|
1328
1549
|
}));
|
|
1329
1550
|
var abortSymbol = Symbol();
|
|
1330
|
-
var connectionOptionsSchema =
|
|
1331
|
-
url:
|
|
1332
|
-
|
|
1333
|
-
|
|
1551
|
+
var connectionOptionsSchema = z9.object({
|
|
1552
|
+
url: z9.union([
|
|
1553
|
+
z9.string().regex(/^amqps?:\/\/(.+):(.+)@(.+)$/).transform((str) => new URL(str)),
|
|
1554
|
+
z9.instanceof(URL).refine((url) => url.protocol.match(/^amqps?:/), "Wrong protocol")
|
|
1334
1555
|
]),
|
|
1335
|
-
version:
|
|
1336
|
-
name:
|
|
1337
|
-
devOverlay:
|
|
1338
|
-
silent:
|
|
1339
|
-
prefetch:
|
|
1340
|
-
connectionTimeout:
|
|
1341
|
-
heartbeatInterval:
|
|
1342
|
-
connectionOptions:
|
|
1343
|
-
maxMessageSize:
|
|
1344
|
-
passthroughByteReferences:
|
|
1556
|
+
version: z9.string(),
|
|
1557
|
+
name: z9.string().optional(),
|
|
1558
|
+
devOverlay: z9.string().optional(),
|
|
1559
|
+
silent: z9.boolean().optional(),
|
|
1560
|
+
prefetch: z9.number().int().optional(),
|
|
1561
|
+
connectionTimeout: z9.number().positive().default(3000),
|
|
1562
|
+
heartbeatInterval: z9.number().int().positive().optional(),
|
|
1563
|
+
connectionOptions: z9.any().optional(),
|
|
1564
|
+
maxMessageSize: z9.number().int().positive().default(128 * 1024 * 1024),
|
|
1565
|
+
passthroughByteReferences: z9.boolean().optional()
|
|
1345
1566
|
});
|
|
1346
1567
|
function isMessageHandlerGenerator(handler) {
|
|
1347
1568
|
return handler.constructor.name === "GeneratorFunction" || handler.constructor.name === "AsyncGeneratorFunction";
|
|
@@ -1384,6 +1605,7 @@ function createConnection({
|
|
|
1384
1605
|
...rest
|
|
1385
1606
|
}, messageHandler) {
|
|
1386
1607
|
const passthroughByteReferences = rest.passthroughByteReferences ?? false;
|
|
1608
|
+
const canRegisterCallbacks = isMessageHandlerGenerator(messageHandler);
|
|
1387
1609
|
const baseQueue = `${url.username}@${version}`;
|
|
1388
1610
|
const queue = devOverlay ? `${baseQueue}-dev-overlay-${devOverlay}` : baseQueue;
|
|
1389
1611
|
const exchange = url.username;
|
|
@@ -1393,7 +1615,7 @@ function createConnection({
|
|
|
1393
1615
|
clientProperties: {
|
|
1394
1616
|
...connectionOptions?.clientProperties,
|
|
1395
1617
|
...buildServiceClientProperties({
|
|
1396
|
-
libVersion: "javascript@0.8.2-edge.
|
|
1618
|
+
libVersion: "javascript@0.8.2-edge.1156",
|
|
1397
1619
|
serviceVersion: version,
|
|
1398
1620
|
name,
|
|
1399
1621
|
devOverlay: Boolean(devOverlay)
|
|
@@ -1404,14 +1626,14 @@ function createConnection({
|
|
|
1404
1626
|
});
|
|
1405
1627
|
connection.on("disconnect", ({ err }) => {
|
|
1406
1628
|
if (!silent && err) {
|
|
1407
|
-
|
|
1629
|
+
simple_default.error("Requence AMQP connection lost:", err.message);
|
|
1408
1630
|
}
|
|
1409
1631
|
onConnectionStateChange?.({ connected: false, err });
|
|
1410
1632
|
});
|
|
1411
1633
|
let hasConnected = false;
|
|
1412
1634
|
connection.on("connect", () => {
|
|
1413
1635
|
if (hasConnected && !silent) {
|
|
1414
|
-
|
|
1636
|
+
simple_default.info("Requence AMQP reconnected");
|
|
1415
1637
|
}
|
|
1416
1638
|
hasConnected = true;
|
|
1417
1639
|
onConnectionStateChange?.({ connected: true });
|
|
@@ -1443,7 +1665,9 @@ function createConnection({
|
|
|
1443
1665
|
connection.addListener("connectFailed", handleConnectFailed);
|
|
1444
1666
|
});
|
|
1445
1667
|
const connectionId = crypto.randomUUID();
|
|
1446
|
-
const
|
|
1668
|
+
const devSession = devOverlay ? `${baseQueue}#${createHash2("sha256").update(devOverlay).digest("hex").slice(0, 16)}` : "";
|
|
1669
|
+
const backchannelQueue = `${queue}-backchannel-${connectionId}`;
|
|
1670
|
+
const sentComponents = new Set;
|
|
1447
1671
|
const generatorTerminators = new Map;
|
|
1448
1672
|
const callbacks = new Map;
|
|
1449
1673
|
const backchannelInbound = createInboundBoundary(passthroughByteReferences ? { transformer: passthroughInboundTransformer } : {});
|
|
@@ -1473,8 +1697,13 @@ function createConnection({
|
|
|
1473
1697
|
break;
|
|
1474
1698
|
}
|
|
1475
1699
|
case "callback": {
|
|
1700
|
+
const { surface } = backchannelMessage.payload;
|
|
1701
|
+
const { taskId } = backchannelMessage;
|
|
1702
|
+
const report = surface && taskId ? (message2) => reportInteractionFailure({ taskId, surface, message: message2 }) : () => {};
|
|
1476
1703
|
const entry = callbacks.get(backchannelMessage.payload.callbackId);
|
|
1477
1704
|
if (!entry) {
|
|
1705
|
+
simple_default.warn(`Requence: dropped an invocation of callback |${backchannelMessage.payload.callbackId}| — nothing is registered under it, so the message that registered it has settled`);
|
|
1706
|
+
report("the process that drew this surface has finished with it, so nothing ran the handler");
|
|
1478
1707
|
break;
|
|
1479
1708
|
}
|
|
1480
1709
|
let arg;
|
|
@@ -1483,10 +1712,16 @@ function createConnection({
|
|
|
1483
1712
|
onCallbackInvoke: entry.onCallbackInvoke
|
|
1484
1713
|
});
|
|
1485
1714
|
} catch (error) {
|
|
1486
|
-
|
|
1715
|
+
simple_default.warn(`dropped callback invocation |${backchannelMessage.payload.callbackId}|: argument rehydration failed`, error instanceof Error ? error.message : error);
|
|
1716
|
+
report("the interaction could not be delivered: its argument could not be read");
|
|
1487
1717
|
break;
|
|
1488
1718
|
}
|
|
1489
|
-
|
|
1719
|
+
try {
|
|
1720
|
+
await entry.callback(arg);
|
|
1721
|
+
} catch (error) {
|
|
1722
|
+
simple_default.error(`Requence: callback |${backchannelMessage.payload.callbackId}| threw:`, error instanceof Error ? error.stack ?? error.message : error);
|
|
1723
|
+
report(`the handler failed: ${errorText(error)}`);
|
|
1724
|
+
}
|
|
1490
1725
|
break;
|
|
1491
1726
|
}
|
|
1492
1727
|
}
|
|
@@ -1497,7 +1732,101 @@ function createConnection({
|
|
|
1497
1732
|
});
|
|
1498
1733
|
channelWrapper.on("error", (err) => {
|
|
1499
1734
|
if (!silent) {
|
|
1500
|
-
|
|
1735
|
+
simple_default.error("Requence AMQP channel error:", err.message);
|
|
1736
|
+
}
|
|
1737
|
+
});
|
|
1738
|
+
const reportInteractionFailure = (params) => {
|
|
1739
|
+
channelWrapper.publish(exchange, "", Buffer.from(JSON.stringify({
|
|
1740
|
+
surface: params.surface,
|
|
1741
|
+
message: params.message.slice(0, MAX_SURFACE_INTERACTION_ERROR_CHARS)
|
|
1742
|
+
})), {
|
|
1743
|
+
contentType: "application/json",
|
|
1744
|
+
persistent: true,
|
|
1745
|
+
headers: {
|
|
1746
|
+
taskId: params.taskId,
|
|
1747
|
+
[SURFACE_INTERACTION_ERROR_HEADER]: true
|
|
1748
|
+
}
|
|
1749
|
+
}).catch((error) => {
|
|
1750
|
+
simple_default.error(`Requence: could not report a failed surface interaction on |${params.surface}|:`, error instanceof Error ? error.message : error);
|
|
1751
|
+
});
|
|
1752
|
+
};
|
|
1753
|
+
const publishBundleSwap = (ui) => {
|
|
1754
|
+
const swap = {
|
|
1755
|
+
devSession,
|
|
1756
|
+
uiId: ui.id,
|
|
1757
|
+
hash: ui.hash,
|
|
1758
|
+
source: ui.source
|
|
1759
|
+
};
|
|
1760
|
+
channelWrapper.publish(exchange, "", Buffer.from(JSON.stringify(swap)), {
|
|
1761
|
+
contentType: "application/json",
|
|
1762
|
+
persistent: true,
|
|
1763
|
+
headers: { [UI_REBUILD_HEADER]: true }
|
|
1764
|
+
}).then(() => {
|
|
1765
|
+
if (!silent) {
|
|
1766
|
+
simple_default.info(`Requence: component |${ui.id}| rebuilt (${ui.hash.slice(0, 12)}) — swapped on every surface of this dev session`);
|
|
1767
|
+
}
|
|
1768
|
+
}).catch((error) => {
|
|
1769
|
+
simple_default.error(`Requence: could not publish the rebuild of |${ui.id}|:`, error instanceof Error ? error.message : error);
|
|
1770
|
+
});
|
|
1771
|
+
};
|
|
1772
|
+
const stopUIWatch = devSession ? watchUIRebuilds({
|
|
1773
|
+
onRebuild: publishBundleSwap,
|
|
1774
|
+
onWarning: (warning) => {
|
|
1775
|
+
if (!silent) {
|
|
1776
|
+
simple_default.warn(warning);
|
|
1777
|
+
}
|
|
1778
|
+
}
|
|
1779
|
+
}) : undefined;
|
|
1780
|
+
const runHandlerInvocation = async (raw) => {
|
|
1781
|
+
const parsed = surfaceHandlerInvocationSchema.safeParse(raw);
|
|
1782
|
+
if (!parsed.success) {
|
|
1783
|
+
simple_default.error("Requence: dropped a malformed surface handler invocation:", parsed.error.message);
|
|
1784
|
+
return;
|
|
1785
|
+
}
|
|
1786
|
+
const { taskId, surface, uiId, path: path2, arg } = parsed.data;
|
|
1787
|
+
const where = `UI |${uiId}| prop |${path2.join(".") || "<root>"}| (task |${taskId}|)`;
|
|
1788
|
+
const report = (message) => reportInteractionFailure({ taskId, surface, message });
|
|
1789
|
+
const ui = findUIById(uiId);
|
|
1790
|
+
if (!ui) {
|
|
1791
|
+
simple_default.error(`Requence: no component registered as |${uiId}| — dropped a handler invocation for ${where}`);
|
|
1792
|
+
report(`the service has no component registered as "${uiId}", so nothing ran the handler`);
|
|
1793
|
+
return;
|
|
1794
|
+
}
|
|
1795
|
+
const handler = getByPath(ui.defaults, path2);
|
|
1796
|
+
if (typeof handler !== "function") {
|
|
1797
|
+
simple_default.error(`Requence: no handler at ${where} — the component's defaults have ${handler === undefined ? "nothing" : typeof handler} there`);
|
|
1798
|
+
report(`this component has no handler at "${path2.join(".") || "<root>"}", so nothing ran`);
|
|
1799
|
+
return;
|
|
1800
|
+
}
|
|
1801
|
+
try {
|
|
1802
|
+
await handler(arg);
|
|
1803
|
+
} catch (error) {
|
|
1804
|
+
report(`the handler failed: ${errorText(error)}`);
|
|
1805
|
+
throw error;
|
|
1806
|
+
}
|
|
1807
|
+
};
|
|
1808
|
+
const handlerQueue = serviceHandlerQueueName(queue);
|
|
1809
|
+
const handlerChannelWrapper = connection.createChannel({
|
|
1810
|
+
async setup(channel) {
|
|
1811
|
+
await channel.assertQueue(handlerQueue, SURFACE_HANDLER_QUEUE_ARGUMENTS);
|
|
1812
|
+
await channel.bindQueue(handlerQueue, "service", handlerQueue);
|
|
1813
|
+
await channel.prefetch(prefetch);
|
|
1814
|
+
await channel.consume(handlerQueue, async (message) => {
|
|
1815
|
+
if (!message) {
|
|
1816
|
+
return;
|
|
1817
|
+
}
|
|
1818
|
+
try {
|
|
1819
|
+
await runHandlerInvocation(JSON.parse(message.content.toString()));
|
|
1820
|
+
} catch (error) {
|
|
1821
|
+
simple_default.error("Requence: surface handler threw:", error instanceof Error ? error.stack ?? error.message : error);
|
|
1822
|
+
}
|
|
1823
|
+
safeAck(channel, message);
|
|
1824
|
+
});
|
|
1825
|
+
}
|
|
1826
|
+
});
|
|
1827
|
+
handlerChannelWrapper.on("error", (err) => {
|
|
1828
|
+
if (!silent) {
|
|
1829
|
+
simple_default.error("Requence AMQP handler channel error:", err.message);
|
|
1501
1830
|
}
|
|
1502
1831
|
});
|
|
1503
1832
|
const publish = ({
|
|
@@ -1574,6 +1903,71 @@ function createConnection({
|
|
|
1574
1903
|
}
|
|
1575
1904
|
};
|
|
1576
1905
|
};
|
|
1906
|
+
const buildRender = (deps) => {
|
|
1907
|
+
const registerSurfaceHandler = (ui, handler, payloadPath) => {
|
|
1908
|
+
const [layer, ...path2] = payloadPath;
|
|
1909
|
+
if (layer === "defaults") {
|
|
1910
|
+
return {
|
|
1911
|
+
__REQUENCE_type: SURFACE_HANDLER_TAG,
|
|
1912
|
+
lifetime: "durable",
|
|
1913
|
+
uiId: ui.id,
|
|
1914
|
+
path: path2
|
|
1915
|
+
};
|
|
1916
|
+
}
|
|
1917
|
+
if (layer !== "props") {
|
|
1918
|
+
throw new Error(`a function in a render payload is only a handler under props or defaults (found at "${payloadPath.join(".")}")`);
|
|
1919
|
+
}
|
|
1920
|
+
const { sourceId, callbackId } = deps.registerCallback(handler);
|
|
1921
|
+
return {
|
|
1922
|
+
__REQUENCE_type: SURFACE_HANDLER_TAG,
|
|
1923
|
+
lifetime: "connection",
|
|
1924
|
+
uiId: ui.id,
|
|
1925
|
+
path: path2,
|
|
1926
|
+
connectionId: sourceId,
|
|
1927
|
+
handlerId: callbackId
|
|
1928
|
+
};
|
|
1929
|
+
};
|
|
1930
|
+
const renderSurface = (params) => {
|
|
1931
|
+
const index = deps.nextIndex();
|
|
1932
|
+
const sentKey = `${deps.taskId}:${params.ui.hash}`;
|
|
1933
|
+
const withSource = !sentComponents.has(sentKey);
|
|
1934
|
+
if (withSource) {
|
|
1935
|
+
sentComponents.add(sentKey);
|
|
1936
|
+
}
|
|
1937
|
+
const issue = () => deps.outbound.send({
|
|
1938
|
+
component: withSource ? {
|
|
1939
|
+
id: params.ui.id,
|
|
1940
|
+
hash: params.ui.hash,
|
|
1941
|
+
source: params.ui.source
|
|
1942
|
+
} : { id: params.ui.id, hash: params.ui.hash },
|
|
1943
|
+
props: params.props,
|
|
1944
|
+
...params.ui.defaults === undefined ? {} : { defaults: params.ui.defaults },
|
|
1945
|
+
surfaceId: params.surfaceId,
|
|
1946
|
+
devSession: devSession || null
|
|
1947
|
+
}, {
|
|
1948
|
+
outputName: null,
|
|
1949
|
+
inlineKeys: ["component", "defaults"],
|
|
1950
|
+
onSurfaceHandler: (handler, path2) => registerSurfaceHandler(params.ui, handler, path2)
|
|
1951
|
+
}).then((data) => publish({
|
|
1952
|
+
index,
|
|
1953
|
+
version,
|
|
1954
|
+
messageId: deps.messageId,
|
|
1955
|
+
taskId: deps.taskId,
|
|
1956
|
+
data,
|
|
1957
|
+
render: true,
|
|
1958
|
+
...deps.priority === undefined ? {} : { priority: deps.priority },
|
|
1959
|
+
...deps.epoch === undefined ? {} : { epoch: deps.epoch }
|
|
1960
|
+
}));
|
|
1961
|
+
const gated = deps.gate?.();
|
|
1962
|
+
deps.outbound.track((gated ? gated.then(issue) : issue()).catch((error) => {
|
|
1963
|
+
if (withSource) {
|
|
1964
|
+
sentComponents.delete(sentKey);
|
|
1965
|
+
}
|
|
1966
|
+
throw error;
|
|
1967
|
+
}));
|
|
1968
|
+
};
|
|
1969
|
+
return renderSurface;
|
|
1970
|
+
};
|
|
1577
1971
|
channelWrapper.addSetup(async (channel) => {
|
|
1578
1972
|
channel.consume(queue, async (message) => {
|
|
1579
1973
|
if (!message) {
|
|
@@ -1623,7 +2017,7 @@ function createConnection({
|
|
|
1623
2017
|
maxFileSize: payload.options.maxFileSize,
|
|
1624
2018
|
wireCodec: dispatchCodec,
|
|
1625
2019
|
signal: abortController.signal,
|
|
1626
|
-
warn: (msg, error) =>
|
|
2020
|
+
warn: (msg, error) => simple_default.warn(`${msg} (task ${taskId})`, error instanceof Error ? error.message : error ?? "")
|
|
1627
2021
|
});
|
|
1628
2022
|
const dispatchInvocation = (params) => {
|
|
1629
2023
|
outbound.track(outbound.send(params.arg, {
|
|
@@ -1642,6 +2036,21 @@ function createConnection({
|
|
|
1642
2036
|
epoch
|
|
1643
2037
|
})));
|
|
1644
2038
|
};
|
|
2039
|
+
const publishDeps = {
|
|
2040
|
+
outbound,
|
|
2041
|
+
registerCallback,
|
|
2042
|
+
taskId,
|
|
2043
|
+
messageId,
|
|
2044
|
+
nextIndex: () => publishIndex++,
|
|
2045
|
+
epoch,
|
|
2046
|
+
priority: message.properties.priority
|
|
2047
|
+
};
|
|
2048
|
+
const onRender = buildRender({
|
|
2049
|
+
...publishDeps,
|
|
2050
|
+
registerCallback: canRegisterCallbacks ? registerCallback : () => {
|
|
2051
|
+
throw new Error("A LINEAR version handler may not register function props — the registration dies when the handler returns. To wait for a viewer, call context.defer() and declare the handler in the UI defaults instead: a durable handler outlives this process.");
|
|
2052
|
+
}
|
|
2053
|
+
});
|
|
1645
2054
|
const [extendedContext, terminatePromise] = await createContextHelper({
|
|
1646
2055
|
taskId,
|
|
1647
2056
|
input: payload.input,
|
|
@@ -1649,15 +2058,7 @@ function createConnection({
|
|
|
1649
2058
|
abortController,
|
|
1650
2059
|
passthroughByteReferences,
|
|
1651
2060
|
sends: {
|
|
1652
|
-
...buildSendApi(
|
|
1653
|
-
outbound,
|
|
1654
|
-
registerCallback,
|
|
1655
|
-
taskId,
|
|
1656
|
-
messageId,
|
|
1657
|
-
nextIndex: () => publishIndex++,
|
|
1658
|
-
epoch,
|
|
1659
|
-
priority: message.properties.priority
|
|
1660
|
-
}),
|
|
2061
|
+
...buildSendApi(publishDeps),
|
|
1661
2062
|
invokeCallback: (ref, arg) => dispatchInvocation({
|
|
1662
2063
|
sourceId: ref.sourceId,
|
|
1663
2064
|
callbackId: ref.callbackId,
|
|
@@ -1685,6 +2086,7 @@ function createConnection({
|
|
|
1685
2086
|
});
|
|
1686
2087
|
});
|
|
1687
2088
|
},
|
|
2089
|
+
onRender,
|
|
1688
2090
|
onDefer(reason) {
|
|
1689
2091
|
deferred = true;
|
|
1690
2092
|
deferredReason = reason || null;
|
|
@@ -1701,7 +2103,7 @@ function createConnection({
|
|
|
1701
2103
|
begin: true,
|
|
1702
2104
|
epoch,
|
|
1703
2105
|
...buildServiceIdentityHeaders({
|
|
1704
|
-
libVersion: "javascript@0.8.2-edge.
|
|
2106
|
+
libVersion: "javascript@0.8.2-edge.1156",
|
|
1705
2107
|
name
|
|
1706
2108
|
})
|
|
1707
2109
|
});
|
|
@@ -1741,7 +2143,7 @@ function createConnection({
|
|
|
1741
2143
|
const { value: result, done } = next;
|
|
1742
2144
|
if (deferred) {
|
|
1743
2145
|
deferred = false;
|
|
1744
|
-
|
|
2146
|
+
simple_default.warn("returning a value in a deferred message resets the deferred status");
|
|
1745
2147
|
}
|
|
1746
2148
|
const { value: rawValue, outputName } = unwrapOutputValue(result);
|
|
1747
2149
|
const value = await outbound.send(rawValue, {
|
|
@@ -1775,7 +2177,7 @@ function createConnection({
|
|
|
1775
2177
|
}
|
|
1776
2178
|
});
|
|
1777
2179
|
if (deferred && value) {
|
|
1778
|
-
|
|
2180
|
+
simple_default.warn("returning a value in a deferred message resets the deferred status");
|
|
1779
2181
|
deferred = false;
|
|
1780
2182
|
}
|
|
1781
2183
|
if (!deferred || value) {
|
|
@@ -1834,14 +2236,14 @@ function createConnection({
|
|
|
1834
2236
|
};
|
|
1835
2237
|
channelWrapper.publish(`${exchange}-retry`, version, message.content, properties).catch((publishError) => {
|
|
1836
2238
|
if (!silent) {
|
|
1837
|
-
|
|
2239
|
+
simple_default.error("Failed to republish message for retry:", publishError);
|
|
1838
2240
|
}
|
|
1839
2241
|
});
|
|
1840
2242
|
return;
|
|
1841
2243
|
}
|
|
1842
2244
|
if (error instanceof UnsupportedCapabilityError) {
|
|
1843
2245
|
if (!silent) {
|
|
1844
|
-
|
|
2246
|
+
simple_default.error(error.message);
|
|
1845
2247
|
}
|
|
1846
2248
|
if (!acked) {
|
|
1847
2249
|
safeAck(channel, message);
|
|
@@ -1857,7 +2259,7 @@ function createConnection({
|
|
|
1857
2259
|
}
|
|
1858
2260
|
}).catch((publishError) => {
|
|
1859
2261
|
if (!silent) {
|
|
1860
|
-
|
|
2262
|
+
simple_default.error("Failed to publish capability mismatch message:", publishError);
|
|
1861
2263
|
}
|
|
1862
2264
|
});
|
|
1863
2265
|
return;
|
|
@@ -1876,7 +2278,7 @@ function createConnection({
|
|
|
1876
2278
|
}
|
|
1877
2279
|
}).catch((publishError) => {
|
|
1878
2280
|
if (!silent) {
|
|
1879
|
-
|
|
2281
|
+
simple_default.error("Failed to publish abort message:", publishError);
|
|
1880
2282
|
}
|
|
1881
2283
|
});
|
|
1882
2284
|
return;
|
|
@@ -1889,8 +2291,8 @@ function createConnection({
|
|
|
1889
2291
|
}
|
|
1890
2292
|
if (error instanceof Error) {
|
|
1891
2293
|
if (!silent) {
|
|
1892
|
-
|
|
1893
|
-
|
|
2294
|
+
simple_default.error("Encountered an error inside service handler:");
|
|
2295
|
+
simple_default.error(error);
|
|
1894
2296
|
}
|
|
1895
2297
|
if (!acked) {
|
|
1896
2298
|
safeAck(channel, message);
|
|
@@ -1906,7 +2308,7 @@ function createConnection({
|
|
|
1906
2308
|
}
|
|
1907
2309
|
}).catch((publishError) => {
|
|
1908
2310
|
if (!silent) {
|
|
1909
|
-
|
|
2311
|
+
simple_default.error("Failed to publish exception message:", publishError);
|
|
1910
2312
|
}
|
|
1911
2313
|
});
|
|
1912
2314
|
return;
|
|
@@ -1924,6 +2326,8 @@ function createConnection({
|
|
|
1924
2326
|
const activeMessageKeys = new Set;
|
|
1925
2327
|
const api = {
|
|
1926
2328
|
close: async () => {
|
|
2329
|
+
stopUIWatch?.();
|
|
2330
|
+
await handlerChannelWrapper.close();
|
|
1927
2331
|
await channelWrapper.close();
|
|
1928
2332
|
await connection.close();
|
|
1929
2333
|
},
|
|
@@ -1967,15 +2371,24 @@ function createConnection({
|
|
|
1967
2371
|
propertyPath: params.propertyPath
|
|
1968
2372
|
})));
|
|
1969
2373
|
};
|
|
2374
|
+
const publishDeps = {
|
|
2375
|
+
outbound,
|
|
2376
|
+
registerCallback,
|
|
2377
|
+
taskId,
|
|
2378
|
+
messageId,
|
|
2379
|
+
nextIndex: () => publishIndex++,
|
|
2380
|
+
gate: activeMessage
|
|
2381
|
+
};
|
|
2382
|
+
const renderSurface = buildRender(publishDeps);
|
|
1970
2383
|
const sendApi = {
|
|
1971
|
-
...buildSendApi(
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
}
|
|
2384
|
+
...buildSendApi(publishDeps),
|
|
2385
|
+
render(ui, props, renderOptions) {
|
|
2386
|
+
renderSurface({
|
|
2387
|
+
ui,
|
|
2388
|
+
props,
|
|
2389
|
+
surfaceId: renderOptions?.surfaceId ?? DEFAULT_SURFACE_ID
|
|
2390
|
+
});
|
|
2391
|
+
},
|
|
1979
2392
|
async abort(error) {
|
|
1980
2393
|
await activeMessage();
|
|
1981
2394
|
channelWrapper.publish(`${exchange}-retry`, "operator", error instanceof Error ? error.message : error, {
|
|
@@ -2027,6 +2440,30 @@ function createConnection({
|
|
|
2027
2440
|
};
|
|
2028
2441
|
return api;
|
|
2029
2442
|
}
|
|
2443
|
+
// src/ui.ts
|
|
2444
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
2445
|
+
import fs2 from "node:fs";
|
|
2446
|
+
import { basename } from "node:path";
|
|
2447
|
+
import { fileURLToPath } from "node:url";
|
|
2448
|
+
function createUI(target, defaults) {
|
|
2449
|
+
const options = target instanceof URL ? { url: target } : target;
|
|
2450
|
+
if (!(options?.url instanceof URL) || options.url.protocol !== "file:") {
|
|
2451
|
+
throw new Error("createUI needs a file URL to the built component: new URL('./component.js', import.meta.url)");
|
|
2452
|
+
}
|
|
2453
|
+
const path2 = fileURLToPath(options.url);
|
|
2454
|
+
const bundle = fs2.readFileSync(path2);
|
|
2455
|
+
if (bundle.byteLength > MAX_UI_SOURCE_BYTES) {
|
|
2456
|
+
throw new UITooLargeError(path2, bundle.byteLength, MAX_UI_SOURCE_BYTES);
|
|
2457
|
+
}
|
|
2458
|
+
const ui = {
|
|
2459
|
+
id: options.id ?? basename(path2),
|
|
2460
|
+
hash: createHash3("sha256").update(bundle).digest("hex"),
|
|
2461
|
+
source: bundle.toString("utf-8"),
|
|
2462
|
+
...defaults === undefined ? {} : { defaults: { ...defaults } }
|
|
2463
|
+
};
|
|
2464
|
+
registerUI(ui, path2);
|
|
2465
|
+
return ui;
|
|
2466
|
+
}
|
|
2030
2467
|
// src/utils.ts
|
|
2031
2468
|
function isAsyncIterable(iterable) {
|
|
2032
2469
|
return typeof iterable[Symbol.asyncIterator] === "function";
|
|
@@ -2124,7 +2561,7 @@ function resolveConnectionOptions(connectionOptions) {
|
|
|
2124
2561
|
if (caEnv) {
|
|
2125
2562
|
tlsDefaults.ca = caEnv;
|
|
2126
2563
|
} else if (caFileEnv) {
|
|
2127
|
-
tlsDefaults.ca =
|
|
2564
|
+
tlsDefaults.ca = fs3.readFileSync(caFileEnv);
|
|
2128
2565
|
}
|
|
2129
2566
|
if (Object.keys(tlsDefaults).length === 0) {
|
|
2130
2567
|
return connectionOptions;
|
|
@@ -2134,10 +2571,11 @@ function resolveConnectionOptions(connectionOptions) {
|
|
|
2134
2571
|
var pkgJson;
|
|
2135
2572
|
function loadPkgJson() {
|
|
2136
2573
|
if (!pkgJson) {
|
|
2137
|
-
pkgJson = JSON.parse(
|
|
2574
|
+
pkgJson = JSON.parse(fs3.readFileSync("package.json", "utf-8"));
|
|
2138
2575
|
}
|
|
2139
2576
|
return pkgJson;
|
|
2140
2577
|
}
|
|
2578
|
+
var didWarnDevToken = false;
|
|
2141
2579
|
function createService(optionsOrVersion, optionalMessageHandler) {
|
|
2142
2580
|
let options;
|
|
2143
2581
|
let messageHandler;
|
|
@@ -2182,6 +2620,10 @@ function createService(optionsOrVersion, optionalMessageHandler) {
|
|
|
2182
2620
|
throw new Error("invalid dev token: access token and dev token belong to different requence instances");
|
|
2183
2621
|
}
|
|
2184
2622
|
devOverlay = devParts[1];
|
|
2623
|
+
if (!didWarnDevToken) {
|
|
2624
|
+
didWarnDevToken = true;
|
|
2625
|
+
simple_default.warn("Requence: started with a |dev token| — this worker consumes a personal dev-overlay queue instead of the deployed version, and that queue is deleted shortly after the process stops. Do not deploy with one: unset |REQUENCE_DEV_TOKEN| / |REQUENCE_SERVICE_DEV_TOKEN|, or remove |requence.devToken| from package.json.");
|
|
2626
|
+
}
|
|
2185
2627
|
}
|
|
2186
2628
|
const envMaxMessageSize = process.env.REQUENCE_MAX_MESSAGE_SIZE ? Number(process.env.REQUENCE_MAX_MESSAGE_SIZE) : undefined;
|
|
2187
2629
|
return createConnection({
|
|
@@ -2199,11 +2641,13 @@ export {
|
|
|
2199
2641
|
wrapIterable,
|
|
2200
2642
|
reachableFetch,
|
|
2201
2643
|
isUnreachableStatus,
|
|
2644
|
+
createUI,
|
|
2202
2645
|
createService,
|
|
2203
2646
|
createCallback,
|
|
2204
2647
|
asyncEventEmitter,
|
|
2205
2648
|
assertReachable,
|
|
2206
2649
|
UnsupportedCapabilityError,
|
|
2650
|
+
UITooLargeError,
|
|
2207
2651
|
RequenceUnreachableError,
|
|
2208
2652
|
RequenceStream,
|
|
2209
2653
|
RequenceFile,
|
|
@@ -2211,5 +2655,5 @@ export {
|
|
|
2211
2655
|
PayloadTooLargeError
|
|
2212
2656
|
};
|
|
2213
2657
|
|
|
2214
|
-
//# debugId=
|
|
2658
|
+
//# debugId=35955FCD96E8C5C764756E2164756E21
|
|
2215
2659
|
//# sourceMappingURL=index.js.map
|