@requence/service 0.8.2-edge.1160 → 0.8.2-edge.1165
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/build/{chunk-gpyt51xn.js → chunk-n7ayk1td.js} +14 -4
- package/build/chunk-n7ayk1td.js.map +15 -0
- package/build/cli.js +1 -1
- package/build/index.js +11 -7
- package/build/index.js.map +3 -3
- package/build/types/helpers/src/protocol/clientProperties.d.ts +40 -2
- package/build/types/helpers/src/protocol/clientProperties.d.ts.map +1 -1
- package/build/types/helpers/src/protocol/update.d.ts +14 -0
- package/build/types/helpers/src/protocol/update.d.ts.map +1 -1
- package/build/types/service/src/createAmqpConnection.d.ts.map +1 -1
- package/package.json +1 -1
- package/build/chunk-gpyt51xn.js.map +0 -15
|
@@ -204,7 +204,9 @@ var CLIENT_PROPERTY_KEYS = {
|
|
|
204
204
|
serviceVersion: "requence_service_version",
|
|
205
205
|
capabilities: "requence_capabilities",
|
|
206
206
|
name: "requence_name",
|
|
207
|
-
devOverlay: "requence_dev_overlay"
|
|
207
|
+
devOverlay: "requence_dev_overlay",
|
|
208
|
+
connectionId: "requence_connection_id",
|
|
209
|
+
prefetch: "requence_prefetch"
|
|
208
210
|
};
|
|
209
211
|
var MAX_SERVICE_NAME_LENGTH = 64;
|
|
210
212
|
var MAX_CAPABILITIES_LENGTH = 512;
|
|
@@ -221,6 +223,8 @@ function sanitizeLabel(value, maxLength) {
|
|
|
221
223
|
function buildServiceClientProperties({
|
|
222
224
|
libVersion,
|
|
223
225
|
serviceVersion,
|
|
226
|
+
connectionId,
|
|
227
|
+
prefetch,
|
|
224
228
|
name,
|
|
225
229
|
devOverlay = false,
|
|
226
230
|
capabilities = SERVICE_WIRE_CAPABILITIES
|
|
@@ -228,6 +232,8 @@ function buildServiceClientProperties({
|
|
|
228
232
|
const properties = {
|
|
229
233
|
[CLIENT_PROPERTY_KEYS.libVersion]: libVersion,
|
|
230
234
|
[CLIENT_PROPERTY_KEYS.serviceVersion]: serviceVersion,
|
|
235
|
+
[CLIENT_PROPERTY_KEYS.connectionId]: connectionId,
|
|
236
|
+
[CLIENT_PROPERTY_KEYS.prefetch]: String(prefetch),
|
|
231
237
|
[CLIENT_PROPERTY_KEYS.capabilities]: capabilities.join(",").slice(0, MAX_CAPABILITIES_LENGTH)
|
|
232
238
|
};
|
|
233
239
|
const label = name ? sanitizeLabel(name, MAX_SERVICE_NAME_LENGTH) : "";
|
|
@@ -272,15 +278,19 @@ function unsupportedCapabilityMessage(unsupported) {
|
|
|
272
278
|
var IDENTITY_HEADER_KEYS = {
|
|
273
279
|
libVersion: "libVersion",
|
|
274
280
|
name: "serviceName",
|
|
275
|
-
capabilities: "capabilities"
|
|
281
|
+
capabilities: "capabilities",
|
|
282
|
+
connectionId: "connectionId",
|
|
283
|
+
holdsSlot: "holdsSlot"
|
|
276
284
|
};
|
|
277
285
|
function buildServiceIdentityHeaders({
|
|
278
286
|
libVersion,
|
|
287
|
+
holdsSlot,
|
|
279
288
|
name,
|
|
280
289
|
capabilities = SERVICE_WIRE_CAPABILITIES
|
|
281
290
|
}) {
|
|
282
291
|
const headers = {
|
|
283
292
|
[IDENTITY_HEADER_KEYS.libVersion]: libVersion,
|
|
293
|
+
[IDENTITY_HEADER_KEYS.holdsSlot]: holdsSlot ? "1" : "0",
|
|
284
294
|
[IDENTITY_HEADER_KEYS.capabilities]: capabilities.join(",").slice(0, MAX_CAPABILITIES_LENGTH)
|
|
285
295
|
};
|
|
286
296
|
const label = name ? sanitizeLabel(name, MAX_SERVICE_NAME_LENGTH) : "";
|
|
@@ -357,5 +367,5 @@ class PayloadTooLargeError extends Error {
|
|
|
357
367
|
|
|
358
368
|
export { __toESM, __commonJS, obfuscate, deobfuscate, simple_default, buildServiceClientProperties, CAPABILITY_HEADER_KEYS, readRequiredCapabilities, unsupportedCapabilities, buildServiceIdentityHeaders, RequenceConnectionError, RequenceUnreachableError, isUnreachableStatus, assertReachable, reachableFetch, UITooLargeError, UnsupportedCapabilityError, PayloadTooLargeError };
|
|
359
369
|
|
|
360
|
-
//# debugId=
|
|
361
|
-
//# sourceMappingURL=chunk-
|
|
370
|
+
//# debugId=E6757BB03F8F29A164756E2164756E21
|
|
371
|
+
//# sourceMappingURL=chunk-n7ayk1td.js.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../helpers/src/utils/obfuscate.ts", "../../logger/src/colors.ts", "../../logger/src/format.ts", "../../logger/src/simple.ts", "../../helpers/src/protocol/clientProperties.ts", "../src/errors.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"const separator = '\\u{f6ee}'\n\nconst base65Chars =\n 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$'\n\nconst base65CharToIndex: Record<string, number> = {}\nfor (let i = 0; i < base65Chars.length; i++) {\n base65CharToIndex[base65Chars[i]] = i\n}\n\nexport function obfuscate(...parts: Array<string>) {\n const str = parts.join(separator)\n let binaryString = ''\n\n for (let i = 0; i < str.length; i++) {\n const charCode = str.charCodeAt(i)\n binaryString += charCode.toString(2).padStart(16, '0')\n }\n\n let encodedString = ''\n const chunkSize = 6\n let paddingCount = 0\n\n for (let i = 0; i < binaryString.length; i += chunkSize) {\n let chunk = binaryString.substring(i, i + chunkSize)\n\n if (chunk.length < chunkSize) {\n paddingCount = chunkSize - chunk.length\n chunk = chunk.padEnd(chunkSize, '0')\n }\n\n const decimalValue = parseInt(chunk, 2)\n encodedString += base65Chars[decimalValue]\n }\n\n return encodedString + paddingCount.toString()\n}\n\nexport function randomString(length: number) {\n const randomValues = new Uint8Array(length)\n crypto.getRandomValues(randomValues)\n\n let randomString = ''\n for (let i = 0; i < length; i++) {\n randomString += base65Chars[randomValues[i] % base65Chars.length]\n }\n\n return randomString\n}\n\nexport function deobfuscate(str: string) {\n const paddingCount = parseInt(str.slice(-1), 10)\n str = str.slice(0, -1)\n\n let binaryString = ''\n\n for (let i = 0; i < str.length; i++) {\n const decimalValue = base65CharToIndex[str[i]]\n const binaryChunk = decimalValue.toString(2).padStart(6, '0')\n binaryString += binaryChunk\n }\n\n if (paddingCount > 0) {\n binaryString = binaryString.slice(0, -paddingCount)\n }\n\n let decodedString = ''\n const charSize = 16\n\n for (let i = 0; i < binaryString.length; i += charSize) {\n const byte = binaryString.substring(i, i + charSize)\n if (byte.length === 16) {\n const charCode = parseInt(byte, 2)\n decodedString += String.fromCharCode(charCode)\n }\n }\n\n return decodedString.split(separator)\n}\n",
|
|
6
|
+
"/**\n * The ANSI styling this package needs, without a dependency.\n *\n * It exists so `./simple` can be imported by a package that ships to npm\n * (`@requence/service`) without dragging a styling library into the published\n * bundle. The emitted escape sequences are byte-identical to the ones chalk\n * produced for every style used here — `colors.spec.ts` is the proof.\n */\n\nconst STYLES = {\n bold: [1, 22],\n black: [30, 39],\n red: [31, 39],\n green: [32, 39],\n yellow: [33, 39],\n blue: [34, 39],\n magenta: [35, 39],\n cyan: [36, 39],\n white: [37, 39],\n gray: [90, 39],\n bgBlack: [40, 49],\n bgRed: [41, 49],\n bgGreen: [42, 49],\n bgYellow: [43, 49],\n bgBlue: [44, 49],\n bgMagenta: [45, 49],\n bgCyan: [46, 49],\n bgWhite: [47, 49],\n} as const satisfies Record<string, readonly [number, number]>\n\ntype StyleName = keyof typeof STYLES\n\ntype Code = readonly [open: string, close: string]\n\nconst forceColor = process.env.FORCE_COLOR\n\n/**\n * Resolved once at load, as a styling library would: the stream a process\n * writes to does not change under it.\n */\nexport const colorEnabled =\n !process.env.NO_COLOR &&\n process.env.TERM !== 'dumb' &&\n (forceColor === undefined\n ? Boolean(process.stdout?.isTTY)\n : forceColor !== '0' && forceColor !== 'false')\n\n/**\n * 24-bit colour is the only thing here that is not universally understood, so\n * it is the only thing gated: everything else is a basic SGR code every\n * terminal has had for decades.\n */\nconst trueColor =\n forceColor === '3' || /truecolor|24bit/i.test(process.env.COLORTERM ?? '')\n\nexport interface Styler {\n (...args: unknown[]): string\n readonly bold: Styler\n readonly black: Styler\n readonly red: Styler\n readonly green: Styler\n readonly yellow: Styler\n readonly blue: Styler\n readonly magenta: Styler\n readonly cyan: Styler\n readonly white: Styler\n readonly gray: Styler\n readonly bgBlack: Styler\n readonly bgRed: Styler\n readonly bgGreen: Styler\n readonly bgYellow: Styler\n readonly bgBlue: Styler\n readonly bgMagenta: Styler\n readonly bgCyan: Styler\n readonly bgWhite: Styler\n /**\n * A 24-bit colour, with the basic colour to fall back on where 24-bit is not\n * available. The fallback is named rather than computed: the palettes here\n * are short and hand-picked, and an approximation nobody chose is worse than\n * the one the author would have chosen.\n */\n hex(value: string, fallback: StyleName): Styler\n}\n\nfunction sequence(code: number) {\n return `\\u001b[${code}m`\n}\n\nfunction createStyler(codes: readonly Code[]): Styler {\n const styler = (...args: unknown[]) => {\n let text = args.map(String).join(' ')\n\n if (!colorEnabled || codes.length === 0) {\n return text\n }\n\n let open = ''\n let close = ''\n for (const [start, end] of codes) {\n open += start\n // A nested style closed this one early. Re-open it right after that\n // close — leaving the close in place, so the nested style still ends\n // where it meant to — and `yellow('a', red('b'), 'c')` is yellow again\n // for the 'c'.\n text = text.includes(end) ? text.replaceAll(end, end + start) : text\n close = end + close\n }\n\n return `${open}${text}${close}`\n }\n\n for (const name of Object.keys(STYLES) as StyleName[]) {\n Object.defineProperty(styler, name, {\n get: () => {\n const [open, close] = STYLES[name]\n return createStyler([...codes, [sequence(open), sequence(close)]])\n },\n })\n }\n\n Object.defineProperty(styler, 'hex', {\n value: (value: string, fallback: StyleName) => {\n if (!trueColor) {\n const [open, close] = STYLES[fallback]\n return createStyler([...codes, [sequence(open), sequence(close)]])\n }\n\n const hex = value.replace('#', '')\n const int = Number.parseInt(hex, 16)\n const r = (int >> 16) & 0xff\n const g = (int >> 8) & 0xff\n const b = int & 0xff\n\n return createStyler([\n ...codes,\n [`\\u001b[38;2;${r};${g};${b}m`, sequence(39)],\n ])\n },\n })\n\n return styler as Styler\n}\n\nexport const colors = createStyler([])\n",
|
|
7
|
+
"import { colors } from './colors.ts'\n\nexport const instanceName = process.env.INSTANCE_NAME || null\n\nexport function withLevel(level: string, message: unknown) {\n let prefix = `??${level}??`\n let highlight = (str: string) => str\n\n switch (level) {\n case 'info': {\n prefix = colors.bgGreen.black.bold(' INFO ')\n highlight = (str) => colors.green.bold(str)\n break\n }\n case 'warn': {\n prefix = colors.bgYellow.black.bold(' WARN ')\n highlight = (str) => colors.yellow.bold(str)\n break\n }\n case 'error': {\n prefix = colors.bgRed.black.bold(' ERROR ')\n highlight = (str) => colors.red.bold(str)\n break\n }\n case 'debug': {\n prefix = colors.bgMagenta.black.bold(' DEBUG ')\n highlight = (str) => colors.magenta.bold(str)\n break\n }\n }\n\n return `${prefix} ${String(message).replace(/\\|(.*?)\\|/g, (_, str) => highlight(str))}`\n}\n",
|
|
8
|
+
"import { colors } from './colors.ts'\nimport { instanceName, withLevel } from './format.ts'\n\ntype Severity = 'error' | 'warn' | 'info'\n\nfunction write(level: Severity, message: unknown, ...rest: unknown[]) {\n let line = `${colors.gray(new Date().toISOString())} ${withLevel(level, message)}`\n\n if (instanceName) {\n line = `${colors.bgBlue.black.bold(` ${instanceName} `)} ${line}`\n }\n\n // Resolved per call, never captured at module load: a severity is also the\n // name of its console method, and a host (or a test) that swaps one expects\n // to intercept what this writes.\n console[level](line, ...rest)\n}\n\n/**\n * A dependency-free logger with the same look as the default export: the same\n * severity prefixes, the same `|highlight|` syntax. Written for packages that\n * ship to npm, where pulling winston into the published bundle costs more than\n * the structured transports are worth.\n *\n * Unlike the default export it has **no levels**. Every call prints, and\n * `LOG_LEVEL` is not read at all. These lines go out from a CLI and from an\n * SDK running inside someone else's process: a line they can lose to an\n * environment variable they did not set for us is worse than no line, because\n * it reads as nothing having happened.\n *\n * That is also why there is no `debug`. A debug level is a promise that\n * something will filter it out later, and nothing here does.\n */\nconst logger = {\n error: (message: unknown, ...rest: unknown[]) =>\n write('error', message, ...rest),\n warn: (message: unknown, ...rest: unknown[]) =>\n write('warn', message, ...rest),\n info: (message: unknown, ...rest: unknown[]) =>\n write('info', message, ...rest),\n}\n\n/**\n * Re-exported here rather than from a second entry point: a consumer that\n * reaches for this logger to avoid the dependency needs the styling for the\n * same reason, and one import path is one thing to keep off the published\n * dependency list.\n */\nexport { type Styler, colorEnabled, colors } from './colors.ts'\n\nexport default logger\n",
|
|
9
|
+
"// AMQP connection client properties: how a service SDK announces itself to the\n// broker at connect time, and how `ui/backend` reads that announcement back.\n//\n// `connection.start-ok` carries a free-form `client-properties` table that the\n// broker keeps for the life of the connection. That makes it the one metadata\n// channel a wire-format change cannot break: it is present BEFORE the first\n// dispatch, it is broker state rather than an event (a `ui/backend` restart just\n// re-reads it), and old SDKs already send amqplib/pika defaults — so a MISSING\n// `requence_*` field means \"too old\", with nothing to negotiate.\n//\n// Read side: `GET /api/connections?columns=name,user,client_properties`. The\n// join key already exists: a service connects with its own AMQP username, and\n// that username IS `service-<internalName>`, so `user` → service and\n// `requence_service_version` → version.\n//\n// THIS FILE IS THE CONTRACT. The Python SDK mirrors it in\n// `python/requence/client_properties.py`, and `python/tests/\n// test_client_properties.py` asserts the key set against this source. Changing\n// a key is a wire change: both SDKs ship it together.\n\n// The pinned, namespaced property set. Flat strings on purpose: a nested field\n// table inside a broker event header is more decode surface than it is worth.\nexport const CLIENT_PROPERTY_KEYS = {\n libVersion: 'requence_lib_version',\n serviceVersion: 'requence_service_version',\n capabilities: 'requence_capabilities',\n // Author-chosen debugging label. Optional, non-unique, unvalidated —\n // NOTHING may key off or branch on it.\n name: 'requence_name',\n // Marks a developer's local dev-overlay connection. Only the marker travels,\n // never the devKey (which is an access-token value).\n devOverlay: 'requence_dev_overlay',\n // WHICH PROCESS this is. Not a new id: it is the same per-connection uuid the\n // SDK already stamps on every publish (and names its backchannel queue with),\n // announced here so a fleet row and a node run can be joined on it. Named for\n // a connection and not a replica because those are not the same thing across a\n // reconnect — the TS SDK keeps its id, the Python SDK mints a new one.\n connectionId: 'requence_connection_id',\n // How many task slots this process has: the consumer prefetch of its DISPATCH\n // channel. The surface-handler and durable-callback channels each get their\n // own budget of the same number, so this is NOT the replica's whole capacity.\n // Per-connection, so client properties are its one correct home — a copy\n // frozen onto a node update would go stale.\n prefetch: 'requence_prefetch',\n} as const\n\n// The name is author-controlled text and the whole client-properties table\n// travels inside the connection frame, so an unbounded string is a\n// connection-level failure. Capped in both SDKs and truncated AGAIN on read.\nexport const MAX_SERVICE_NAME_LENGTH = 64\nexport const MAX_CAPABILITIES_LENGTH = 512\n\n// Wire capabilities. `wire:json1` is the JSON body encoding every shipped SDK\n// speaks and is the floor that never goes away; each additional codec joins this\n// list as its own token, and the fleet fold below is what tells a dispatch whether\n// it may use it.\nexport const WIRE_JSON_1 = 'wire:json1'\n// The portable msgpack subset in `@requence/helpers/msgpack` (`packWire`). Claimed\n// only by an SDK that can DECODE it on the dispatch wire — a service echoes the\n// codec it was addressed in, so claiming this is a promise about reading, and the\n// reply direction needs no capability of its own.\n//\n// Both SDKs claim it now; the Python counterpart is `requence/wire_codec.py`. The\n// two lists are still per-language on purpose — the fleet fold intersects across\n// replicas, so a language that lags simply pulls its fleets back to JSON instead\n// of needing a special case.\nexport const WIRE_MSGPACK_1 = 'wire:msgpack1'\nexport const SERVICE_WIRE_CAPABILITIES: ReadonlyArray<string> = [\n WIRE_JSON_1,\n WIRE_MSGPACK_1,\n]\n\n// oxlint-disable-next-line no-control-regex\nconst CONTROL_CHARACTERS = /[\\u0000-\\u001f\\u007f]/g\n\nfunction sanitizeLabel(value: string, maxLength: number) {\n return value.replace(CONTROL_CHARACTERS, '').trim().slice(0, maxLength)\n}\n\nexport interface BuildServiceClientPropertiesParams {\n /** `<language>@<version>`, e.g. `javascript@1.2.3`. */\n libVersion: string\n /** The service version this connection consumes, e.g. `v1`. */\n serviceVersion: string\n /**\n * This connection's own uuid — the one it already publishes with. REQUIRED,\n * like `prefetch`: both are known at connect time in every SDK, so a forgetful\n * one should fail to compile rather than announce a replica nothing can join.\n */\n connectionId: string\n /** The dispatch channel's prefetch — this connection's task-slot total. */\n prefetch: number\n /** Optional author-chosen debugging label. */\n name?: string\n devOverlay?: boolean\n capabilities?: ReadonlyArray<string>\n}\n\n// Builds the properties a service SDK passes to its AMQP client on connect (and\n// therefore on every reconnect, since both clients reuse their connection\n// parameters). Absent optional fields are OMITTED, never sent blank.\nexport function buildServiceClientProperties({\n libVersion,\n serviceVersion,\n connectionId,\n prefetch,\n name,\n devOverlay = false,\n capabilities = SERVICE_WIRE_CAPABILITIES,\n}: BuildServiceClientPropertiesParams): Record<string, string> {\n const properties: Record<string, string> = {\n [CLIENT_PROPERTY_KEYS.libVersion]: libVersion,\n [CLIENT_PROPERTY_KEYS.serviceVersion]: serviceVersion,\n [CLIENT_PROPERTY_KEYS.connectionId]: connectionId,\n // Stringified, like every other value here: the table is flat strings on\n // purpose. The read side is what decides whether it is a usable number.\n [CLIENT_PROPERTY_KEYS.prefetch]: String(prefetch),\n [CLIENT_PROPERTY_KEYS.capabilities]: capabilities\n .join(',')\n .slice(0, MAX_CAPABILITIES_LENGTH),\n }\n\n const label = name ? sanitizeLabel(name, MAX_SERVICE_NAME_LENGTH) : ''\n if (label) {\n properties[CLIENT_PROPERTY_KEYS.name] = label\n }\n\n if (devOverlay) {\n properties[CLIENT_PROPERTY_KEYS.devOverlay] = '1'\n }\n\n return properties\n}\n\n// One attached replica, as read back off its connection. Every field is\n// nullable: an SDK too old to announce yields a blank replica, which is exactly\n// the signal the fold below needs.\nexport interface ServiceReplica {\n libVersion: string | null\n serviceVersion: string | null\n capabilities: string[]\n name: string | null\n devOverlay: boolean\n /**\n * Null means NOT ATTRIBUTABLE — an SDK too old to announce. Never a default\n * replica: a made-up id would join a fleet row to node runs that were not its.\n */\n connectionId: string | null\n /**\n * The task-slot TOTAL, or null when this replica announced none. Never\n * defaulted to 1: absence is not evidence, and against a real prefetch of 5 a\n * guessed total renders \"2 of 1\". A null total means \"show the used count\n * alone\".\n */\n prefetch: number | null\n}\n\nconst BLANK_REPLICA: ServiceReplica = {\n libVersion: null,\n serviceVersion: null,\n capabilities: [],\n name: null,\n devOverlay: false,\n connectionId: null,\n prefetch: null,\n}\n\nfunction readString(\n table: Record<string, unknown>,\n key: string,\n): string | null {\n const value = table[key]\n return typeof value === 'string' && value.length > 0 ? value : null\n}\n\n// Parses a broker `client_properties` table. Never throws and never trusts the\n// writer: the name and the capability string are re-capped here, so a\n// misbehaving (or malicious) SDK cannot push an unbounded string into the UI.\nexport function readServiceClientProperties(raw: unknown): ServiceReplica {\n if (typeof raw !== 'object' || raw === null) {\n return { ...BLANK_REPLICA }\n }\n\n const table = raw as Record<string, unknown>\n const rawName = readString(table, CLIENT_PROPERTY_KEYS.name)\n const name = rawName ? sanitizeLabel(rawName, MAX_SERVICE_NAME_LENGTH) : null\n\n return {\n libVersion: readString(table, CLIENT_PROPERTY_KEYS.libVersion),\n serviceVersion: readString(table, CLIENT_PROPERTY_KEYS.serviceVersion),\n capabilities: parseCapabilityList(\n readString(table, CLIENT_PROPERTY_KEYS.capabilities),\n ),\n name: name || null,\n devOverlay: readString(table, CLIENT_PROPERTY_KEYS.devOverlay) === '1',\n connectionId: readString(table, CLIENT_PROPERTY_KEYS.connectionId),\n prefetch: readPositiveInteger(\n readString(table, CLIENT_PROPERTY_KEYS.prefetch),\n ),\n }\n}\n\n// A prefetch of 0, a negative, a decimal or a non-number is not a slot total —\n// it is a writer this reader cannot understand, and the only honest answer is\n// \"unknown\". Never 1: see `ServiceReplica.prefetch`.\nfunction readPositiveInteger(raw: string | null): number | null {\n if (!raw || !/^\\d+$/.test(raw)) {\n return null\n }\n const value = Number(raw)\n return Number.isSafeInteger(value) && value > 0 ? value : null\n}\n\n// Caps the whole string BEFORE splitting, so an unbounded writer cannot push an\n// unbounded list through. A token cut in half by that cap simply matches no\n// known capability, which can only ever UNDER-claim — the safe direction.\nfunction parseCapabilityList(raw: string | null): string[] {\n if (!raw) {\n return []\n }\n return [\n ...new Set(\n raw\n .slice(0, MAX_CAPABILITIES_LENGTH)\n .split(',')\n .map((token) => token.trim())\n .filter(Boolean),\n ),\n ]\n}\n\n// The fleet verdict. `libVersion`/`capabilities` are the MINIMUM across every\n// attached replica, because replicas are mixed during a rolling deploy and a\n// verdict that over-claims breaks the one box that cannot honour it.\nexport interface FleetVerdict {\n libVersion: string | null\n capabilities: string[]\n // True when we hold a row for every replica attached to the queue. False\n // means either nothing is attached, or some attached replica is unaccounted\n // for — in both cases the verdict above is deliberately empty.\n complete: boolean\n}\n\n// Leading `major.minor.patch` of the version half of `<language>@<version>`.\n// Null for anything else (`python@dev`, a garbage string), which sorts LOWEST:\n// an unknown build must never win a minimum fold.\nfunction parseLibVersion(libVersion: string): [number, number, number] | null {\n const match = /@(\\d+)\\.(\\d+)\\.(\\d+)/.exec(libVersion)\n if (!match) {\n return null\n }\n return [Number(match[1]), Number(match[2]), Number(match[3])]\n}\n\n// Both SDKs are released from this monorepo at the same version, so comparing\n// only the numeric half is meaningful even across languages — the question is\n// \"what is the oldest build attached\", not \"which language\".\nfunction isLower(candidate: string, current: string) {\n const parsedCandidate = parseLibVersion(candidate)\n const parsedCurrent = parseLibVersion(current)\n\n if (!parsedCandidate) {\n // Two unknowns: pick deterministically so the verdict never flaps.\n return !parsedCurrent ? candidate < current : true\n }\n if (!parsedCurrent) {\n return false\n }\n\n for (let index = 0; index < 3; index++) {\n if (parsedCandidate[index] !== parsedCurrent[index]) {\n return parsedCandidate[index] < parsedCurrent[index]\n }\n }\n return false\n}\n\n// Folds the announced replicas of ONE service version into a single verdict.\n// `attachedCount` is the queue's consumer count (from the queue count monitor):\n// it is what makes a MISSING announcement visible. Fewer rows than consumers\n// means some attached box never announced itself, and the honest answer is\n// \"unknown\" — a wrong fold is worse than no data.\nexport function foldServiceFleet(\n replicas: ReadonlyArray<ServiceReplica>,\n attachedCount: number,\n): FleetVerdict {\n const complete = replicas.length > 0 && replicas.length >= attachedCount\n if (!complete) {\n return { libVersion: null, capabilities: [], complete }\n }\n\n let libVersion: string | null = null\n for (const replica of replicas) {\n if (!replica.libVersion) {\n // One replica too old to announce ⇒ nothing can be claimed for the fleet.\n return { libVersion: null, capabilities: [], complete }\n }\n if (libVersion === null || isLower(replica.libVersion, libVersion)) {\n libVersion = replica.libVersion\n }\n }\n\n const intersection = new Set(replicas[0].capabilities)\n for (const replica of replicas.slice(1)) {\n const declared = new Set(replica.capabilities)\n for (const capability of intersection) {\n if (!declared.has(capability)) {\n intersection.delete(capability)\n }\n }\n }\n\n return {\n libVersion,\n capabilities: [...intersection].sort(),\n complete,\n }\n}\n\n// THE ONE PLACE A CODEC IS CHOSEN, for the whole system.\n//\n// `ui/backend` calls this at task creation and bakes the answer into the compiled\n// tree, so the operator never decides and holds no presence state: it encodes what\n// the tree tells it to, and every receiver reads the content type off the message.\n//\n// Two ways to answer `json`, and both are the safe direction:\n// - the verdict is incomplete (nothing attached, or an attached replica never\n// announced itself) — an unknown fleet is never given a new codec;\n// - the intersection lacks the token — at least one attached replica cannot\n// decode msgpack, and `foldServiceFleet` has already reduced the fleet to what\n// its weakest member can do.\n//\n// The cost of this being frozen at creation is that a long-running continuous task\n// keeps its codec until it is recreated, so the migration completes only as tasks\n// turn over. That is slow, not unsafe.\nexport function wireCodecForFleet(verdict: FleetVerdict): 'json' | 'msgpack' {\n return verdict.complete && verdict.capabilities.includes(WIRE_MSGPACK_1)\n ? 'msgpack'\n : 'json'\n}\n\n// ─── The dispatch direction: what a message REQUIRES of its consumer ────────\n//\n// The fleet fold above answers \"may this dispatch use a capability?\" BEFORE the\n// message is built. `requires` answers the mirror question at the other end:\n// \"did the replica that actually picked this up have it?\" — because a fold is a\n// verdict about the fleet as it was, and a rollback, a scale-up or a wrong\n// verdict can put an incapable box in front of the message anyway.\n//\n// IT IS A HEADER, NEVER A BODY FIELD. The body is precisely the thing an\n// incapable consumer may be unable to decode, so a requirement stated inside it\n// is unreadable exactly when it matters — the same reasoning that put the codec\n// in `content-type`.\n//\n// An SDK too old to know the header ignores it, as it always has: that is a\n// bare unknown header, not an error. So this is insurance for the NEXT\n// capability, not a fix for a rollback under the current one.\nexport const CAPABILITY_HEADER_KEYS = {\n // dispatch → service: the tokens this message needs. Absent when it needs\n // nothing beyond the floor every SDK speaks.\n requires: 'requires',\n // service → operator: this replica cannot satisfy `requires`. Sent by\n // REPUBLISHING to `<exchange>-retry`, never by nacking — a nack cannot modify\n // the message, these are classic queues (so there is no `x-delivery-count`\n // either), and with no counter anywhere the message would requeue forever.\n mismatch: 'capabilityMismatch',\n // operator → service, on a reroute: how many reroutes are left. Named for\n // reroutes and NOT for retries on purpose — it is its own allowance, never the\n // node's `retry` budget, which the template author set aside for real errors.\n // The operator owns the count; see `MAX_CAPABILITY_REROUTES` in its error\n // consumer.\n reroutes: 'capabilityReroutes',\n} as const\n\n// What a dispatch under `codec` needs of the replica that picks it up. `json` is\n// the floor no SDK has ever lacked, so it requires nothing and the header is\n// omitted entirely.\n//\n// For `wire:msgpack1` this buys nothing on its own — `content-type` already\n// carries that requirement and any SDK new enough to read `requires` has the\n// codec. It is stated anyway so the mechanism has exactly one producer, ready\n// for the first capability that is NOT self-describing.\nexport function requiredCapabilitiesForCodec(\n codec: 'json' | 'msgpack',\n): string[] {\n return codec === 'msgpack' ? [WIRE_MSGPACK_1] : []\n}\n\n// The header table for a dispatch, or `{}` when there is nothing to require —\n// spread into the publish, so an empty requirement sends no header at all\n// rather than a blank one.\nexport function buildRequiresHeader(\n capabilities: ReadonlyArray<string>,\n): Record<string, string> {\n if (capabilities.length === 0) {\n return {}\n }\n return {\n [CAPABILITY_HEADER_KEYS.requires]: capabilities\n .join(',')\n .slice(0, MAX_CAPABILITIES_LENGTH),\n }\n}\n\n// Reads `requires` off a message's header table. Never throws and never trusts\n// the writer, exactly like the client-properties read side: an absent, blank or\n// non-string header means \"requires nothing\", which is how every message\n// published before this existed reads.\nexport function readRequiredCapabilities(headers: unknown): string[] {\n if (typeof headers !== 'object' || headers === null) {\n return []\n }\n return parseCapabilityList(\n readString(\n headers as Record<string, unknown>,\n CAPABILITY_HEADER_KEYS.requires,\n ),\n )\n}\n\n// The tokens this consumer cannot satisfy. Anything unrecognised counts as\n// unsupported — an unknown token is a capability from a newer operator, and\n// guessing it is harmless would defeat the whole point of declaring it.\nexport function unsupportedCapabilities(\n required: ReadonlyArray<string>,\n supported: ReadonlyArray<string> = SERVICE_WIRE_CAPABILITIES,\n): string[] {\n const known = new Set(supported)\n return required.filter((token) => !known.has(token))\n}\n\n// The one diagnostic string, so both SDKs report a mismatch identically and the\n// operator can surface it verbatim. Named and deliberate — the point of the\n// whole mechanism is that the failure is this message and never whatever\n// incidental exception the undecodable payload would have produced.\nexport function unsupportedCapabilityMessage(\n unsupported: ReadonlyArray<string>,\n): string {\n return `unsupported wire capability: ${unsupported.join(', ')}`\n}\n\n// ─── The second announcement: per-run identity on the begin message ─────────\n//\n// Mostly the same values as above, sent again — deliberately, because they\n// answer a DIFFERENT question at a different time:\n//\n// - Client properties (above) say \"can this fleet decode msgpack?\". Live broker\n// state, folded to the MINIMUM across replicas, and the only answer available\n// BEFORE dispatch — which is where it must be, since a codec break fails\n// inside the service's own decoder and no reply could warn us.\n// - These headers say \"which build ran THIS node?\". The service stamps them on\n// its `begin` publish, the operator freezes them into the `NODE_START` update,\n// and that row is written once and never re-derived. Exact, not folded: at\n// dispatch time nobody knows which replica will pick the message up, but once\n// it has, only that replica can say who it is.\n//\n// The two can never disagree — both come from the same constants in the same\n// process, through this one file — and neither is ever read to answer the\n// other's question.\n//\n// Sent on `begin` ONLY, not on every reply: one stamp per node execution.\n\n// Bare, un-namespaced names, matching the message headers that already ride\n// alongside them (`taskId`, `index`, `connectionId`, `version`, `epoch`).\n// `libVersion` keeps its historical name — it is the same value it always was.\nexport const IDENTITY_HEADER_KEYS = {\n libVersion: 'libVersion',\n name: 'serviceName',\n capabilities: 'capabilities',\n // READ-ONLY, and the only asymmetry in this dict: every other key here is\n // both built and read, but `buildServiceIdentityHeaders` does NOT emit this\n // one. The base publish header block of both SDKs already stamps\n // `connectionId` on EVERY message, begin included, so emitting it again would\n // write the same value twice into one header table for no gain. It is listed\n // here so the reader picks it up — and so the cross-language key-name parity\n // test covers the name.\n connectionId: 'connectionId',\n // Does THIS run occupy one of the consumer's dispatch prefetch slots — i.e.\n // does its message stay unacked while the work runs? Per run, not per replica.\n // Emitted by the builder (unlike `connectionId`), because it is new.\n holdsSlot: 'holdsSlot',\n} as const\n\n// What ran one node execution. `libVersion` is DISPLAY-ONLY: it may read\n// `javascript@legacy` (see below), so nothing may parse or branch on it — the\n// pre-dispatch capability answer is the fleet fold, never this.\nexport interface ServiceIdentity {\n libVersion: string | null\n name: string | null\n capabilities: string[]\n /** Which process ran it, joinable against `ServiceReplica.connectionId`. */\n connectionId: string | null\n /**\n * Whether this run holds one of that process's task slots. Null — never\n * `false` — when the message carried no flag, because \"holds no slot\" and\n * \"too old to report\" must stay distinguishable.\n */\n holdsSlot: boolean | null\n}\n\nexport interface BuildServiceIdentityHeadersParams {\n libVersion: string\n /**\n * REQUIRED, so a forgetful SDK fails to compile. `!(isGenerator && mode ===\n * 'CONTINUOUS')` at every call site: that one combination acks immediately and\n * frees its slot, every other stays unacked until the work is done.\n */\n holdsSlot: boolean\n name?: string\n capabilities?: ReadonlyArray<string>\n}\n\n// Built by the service, from its own build-time constants. Nothing is looked up,\n// so nothing can be stale or race a lookup.\nexport function buildServiceIdentityHeaders({\n libVersion,\n holdsSlot,\n name,\n capabilities = SERVICE_WIRE_CAPABILITIES,\n}: BuildServiceIdentityHeadersParams): Record<string, string> {\n const headers: Record<string, string> = {\n [IDENTITY_HEADER_KEYS.libVersion]: libVersion,\n // ALWAYS sent, breaking this file's \"absent optional fields are OMITTED\"\n // rule on purpose: omitting `false` would make it indistinguishable from an\n // SDK too old to report, and those two answers are not the same.\n [IDENTITY_HEADER_KEYS.holdsSlot]: holdsSlot ? '1' : '0',\n [IDENTITY_HEADER_KEYS.capabilities]: capabilities\n .join(',')\n .slice(0, MAX_CAPABILITIES_LENGTH),\n }\n\n const label = name ? sanitizeLabel(name, MAX_SERVICE_NAME_LENGTH) : ''\n if (label) {\n headers[IDENTITY_HEADER_KEYS.name] = label\n }\n\n return headers\n}\n\n// `<language>` half of `<language>@<version>`, for the legacy label below. The\n// `@` is required: without it the string makes no language claim at all, and\n// inventing one from a bare token would put a made-up word in the UI.\nfunction libVersionLanguage(libVersion: string): string | null {\n const match = /^([a-z]+)@/i.exec(libVersion.trim())\n return match ? match[1].toLowerCase() : null\n}\n\n// Parses the identity a service stamped on its begin message. Returns null when\n// the message carried none at all — a reference/or node's NODE_START, or the\n// operator's own loopback.\n//\n// THE LEGACY CASE: an SDK from before this existed still sends `libVersion`, but\n// never sent a name or capabilities. Since every current build declares at least\n// `wire:json1`, a MISSING capabilities header is a reliable \"predates this\" —\n// and the version header still names the language, so it reports as\n// `javascript@legacy` / `python@legacy`. That says \"reported before we asked for\n// more\", which is a different thing from \"unknown\".\nexport function readServiceIdentity(raw: unknown): ServiceIdentity | null {\n if (typeof raw !== 'object' || raw === null) {\n return null\n }\n\n const table = raw as Record<string, unknown>\n const libVersion = readString(table, IDENTITY_HEADER_KEYS.libVersion)\n const rawCapabilities = readString(table, IDENTITY_HEADER_KEYS.capabilities)\n\n if (!rawCapabilities) {\n if (!libVersion) {\n return null\n }\n const language = libVersionLanguage(libVersion)\n return {\n libVersion: language ? `${language}@legacy` : 'legacy',\n name: null,\n capabilities: [],\n // Nulls, deliberately, even though such a build does stamp a\n // `connectionId` on its publishes: it announces none in its client\n // properties, so there is no fleet row to join this to. A run that cannot\n // be attributed to a replica is not attributed to one.\n connectionId: null,\n holdsSlot: null,\n }\n }\n\n // Never trust the writer, exactly as on the client-properties read side.\n const rawName = readString(table, IDENTITY_HEADER_KEYS.name)\n const name = rawName ? sanitizeLabel(rawName, MAX_SERVICE_NAME_LENGTH) : ''\n const rawHoldsSlot = readString(table, IDENTITY_HEADER_KEYS.holdsSlot)\n\n return {\n libVersion,\n name: name || null,\n capabilities: parseCapabilityList(rawCapabilities),\n connectionId: readString(table, IDENTITY_HEADER_KEYS.connectionId),\n // Anything that is not one of the two flags reads as \"did not report\",\n // never as `false`.\n holdsSlot:\n rawHoldsSlot === '1' ? true : rawHoldsSlot === '0' ? false : null,\n }\n}\n\n/**\n * WHY a service node got the codec it got.\n *\n * `wireCodecForFleet` answers `json` for several distinct situations that matter\n * very differently in an incident: a service that is simply offline looks nothing\n * like a management API that is down, which in turn looks nothing like a genuine\n * mixed fleet. Recording only the codec makes \"why is this json?\" unanswerable\n * without shell access to the box, so the reason travels beside it.\n *\n * A compact token rather than prose: it is baked into every service node of every\n * task, and the wording belongs to the UI, which can then change without touching\n * the tree or the operator.\n */\n// A literal tuple, so the protocol schemas can build a `z.enum` straight from it\n// and the vocabulary exists in exactly one place.\nexport const WIRE_CODEC_REASON_VALUES = [\n /** msgpack: every attached replica claimed the capability. */\n 'fleet-capable',\n /** The broker's management API is unreachable, so no fleet can be judged. */\n 'presence-unavailable',\n /** Nothing is attached to this service version's queue at all. */\n 'no-replicas',\n /**\n * Something IS consuming the queue that never announced itself. An SDK too old\n * to announce is also too old to decode, so this folds to json — and it is the\n * one reason that looks like a bug but is the design working.\n */\n 'replicas-unaccounted',\n /** A complete fleet, but at least one replica cannot decode msgpack. */\n 'missing-capability',\n] as const\n\nexport type WireCodecReason = (typeof WIRE_CODEC_REASON_VALUES)[number]\n\n/** Named accessors, so call sites read as intent rather than as string literals. */\nexport const WIRE_CODEC_REASONS = {\n fleetCapable: 'fleet-capable',\n presenceUnavailable: 'presence-unavailable',\n noReplicas: 'no-replicas',\n replicasUnaccounted: 'replicas-unaccounted',\n missingCapability: 'missing-capability',\n} as const satisfies Record<string, WireCodecReason>\n\n/**\n * Explains a `json` verdict from the facts the fleet monitor holds.\n *\n * Split from `wireCodecForFleet` rather than folded into it because the codec\n * decision needs only the verdict, while the explanation needs the counts behind\n * it — and the codec must stay trivially checkable.\n */\nexport function wireCodecReason({\n codec,\n presenceAvailable,\n replicaCount,\n consumerCount,\n}: {\n codec: 'json' | 'msgpack'\n presenceAvailable: boolean\n replicaCount: number\n consumerCount: number\n}): WireCodecReason {\n if (codec === 'msgpack') {\n return WIRE_CODEC_REASONS.fleetCapable\n }\n if (!presenceAvailable) {\n return WIRE_CODEC_REASONS.presenceUnavailable\n }\n // Checked before `no-replicas`, so \"nothing announced but something IS\n // consuming\" reports the consumer rather than claiming the service is offline.\n if (replicaCount < consumerCount) {\n return WIRE_CODEC_REASONS.replicasUnaccounted\n }\n if (replicaCount === 0) {\n return WIRE_CODEC_REASONS.noReplicas\n }\n return WIRE_CODEC_REASONS.missingCapability\n}\n",
|
|
10
|
+
"import { unsupportedCapabilityMessage } from '@requence/helpers/protocol'\n\nexport class RequenceConnectionError extends Error {}\n\n// Gateway statuses an ingress/load balancer emits when no healthy backend is\n// available (maintenance window, deploy, cutover). The backend endpoints never\n// return these themselves, so treating them as \"unreachable\" is unambiguous.\nconst UNREACHABLE_STATUS = new Set([502, 503, 504])\n\n/**\n * Signals that the requence system could not be reached — e.g. during a\n * maintenance window or deploy, when the backend is unreachable (connection\n * refused / timeout / DNS failure) or an ingress returns a gateway error\n * (502/503/504). Callers should treat this as transient and retry later.\n */\nexport class RequenceUnreachableError extends Error {\n constructor(\n public readonly status?: number,\n options?: { cause?: unknown },\n ) {\n super(\n 'The requence system is currently not reachable. Please retry later.',\n options,\n )\n this.name = 'RequenceUnreachableError'\n }\n}\n\nexport function isUnreachableStatus(status: number): boolean {\n return UNREACHABLE_STATUS.has(status)\n}\n\n/**\n * Throws a {@link RequenceUnreachableError} when the response carries a gateway\n * status indicating the system is unreachable. Call right after a fetch, before\n * inspecting `response.ok`.\n */\nexport function assertReachable(response: Response): void {\n if (isUnreachableStatus(response.status)) {\n throw new RequenceUnreachableError(response.status)\n }\n}\n\n/**\n * Wraps `fetch` so a transport-level failure (connection refused, DNS failure,\n * timeout) surfaces as a {@link RequenceUnreachableError} instead of a raw\n * TypeError, and gateway statuses (502/503/504) do the same. The returned\n * response is guaranteed not to be a gateway-error response.\n */\nexport async function reachableFetch(\n input: Parameters<typeof fetch>[0],\n init?: Parameters<typeof fetch>[1],\n): Promise<Response> {\n let response: Response\n try {\n response = await fetch(input, init)\n } catch (error) {\n throw new RequenceUnreachableError(undefined, { cause: error })\n }\n assertReachable(response)\n return response\n}\n\n/**\n * A UI component bundle exceeded the hard cap. Thrown by `createUI` at\n * registration: the source travels inline in every first render of its hash, so\n * an oversized bundle is a deploy-time mistake, not a runtime condition.\n */\nexport class UITooLargeError extends Error {\n readonly path: string\n readonly size: number\n readonly maxSize: number\n\n constructor(path: string, size: number, maxSize: number) {\n super(\n `UI component \"${path}\" is ${size} bytes, which exceeds the maximum ` +\n `component size of ${maxSize} bytes. Bundle only the component and its ` +\n `own dependencies — a whole-app bundle travels with every render.`,\n )\n this.name = 'UITooLargeError'\n this.path = path\n this.size = size\n this.maxSize = maxSize\n }\n}\n\n/**\n * The dispatch declared a capability (`requires` header) this build cannot\n * satisfy, so it was refused before its body was ever decoded.\n *\n * A NAMED error on purpose: the point of the `requires` header is that a\n * mismatch reports the missing capability, instead of whatever incidental\n * exception the undecodable payload would otherwise have produced — a bare\n * `SyntaxError` from `JSON.parse` says nothing about why this box was the wrong\n * one. The message travels to the operator, which surfaces it on the node.\n */\nexport class UnsupportedCapabilityError extends Error {\n readonly capabilities: string[]\n\n constructor(unsupported: ReadonlyArray<string>) {\n super(unsupportedCapabilityMessage(unsupported))\n this.name = 'UnsupportedCapabilityError'\n this.capabilities = [...unsupported]\n }\n}\n\nexport class PayloadTooLargeError extends Error {\n readonly size: number\n readonly maxSize: number\n\n constructor(size: number, maxSize: number) {\n super(\n `Message payload is ${size} bytes, which exceeds the maximum message ` +\n `size of ${maxSize} bytes. Reduce the returned value, or offload large ` +\n `data (files/streams) so it travels by reference instead of inline.`,\n )\n this.name = 'PayloadTooLargeError'\n this.size = size\n this.maxSize = maxSize\n }\n}\n"
|
|
11
|
+
],
|
|
12
|
+
"mappings": "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",
|
|
13
|
+
"debugId": "E6757BB03F8F29A164756E2164756E21",
|
|
14
|
+
"names": []
|
|
15
|
+
}
|
package/build/cli.js
CHANGED
package/build/index.js
CHANGED
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
readRequiredCapabilities,
|
|
18
18
|
simple_default,
|
|
19
19
|
unsupportedCapabilities
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-n7ayk1td.js";
|
|
21
21
|
|
|
22
22
|
// ../../node_modules/.bun/dlv@1.1.3/node_modules/dlv/dist/dlv.js
|
|
23
23
|
var require_dlv = __commonJS((exports, module) => {
|
|
@@ -1981,7 +1981,9 @@ function createConnection({
|
|
|
1981
1981
|
...rest
|
|
1982
1982
|
}, messageHandler) {
|
|
1983
1983
|
const passthroughByteReferences = rest.passthroughByteReferences ?? false;
|
|
1984
|
-
const
|
|
1984
|
+
const isGeneratorHandler = isMessageHandlerGenerator(messageHandler);
|
|
1985
|
+
const canRegisterCallbacks = isGeneratorHandler;
|
|
1986
|
+
const connectionId = crypto.randomUUID();
|
|
1985
1987
|
const baseQueue = `${url.username}@${version}`;
|
|
1986
1988
|
const queue = devOverlay ? `${baseQueue}-dev-overlay-${devOverlay}` : baseQueue;
|
|
1987
1989
|
const exchange = url.username;
|
|
@@ -1991,8 +1993,10 @@ function createConnection({
|
|
|
1991
1993
|
clientProperties: {
|
|
1992
1994
|
...connectionOptions?.clientProperties,
|
|
1993
1995
|
...buildServiceClientProperties({
|
|
1994
|
-
libVersion: "javascript@0.8.2-edge.
|
|
1996
|
+
libVersion: "javascript@0.8.2-edge.1165",
|
|
1995
1997
|
serviceVersion: version,
|
|
1998
|
+
connectionId,
|
|
1999
|
+
prefetch,
|
|
1996
2000
|
name,
|
|
1997
2001
|
devOverlay: Boolean(devOverlay)
|
|
1998
2002
|
})
|
|
@@ -2040,7 +2044,6 @@ function createConnection({
|
|
|
2040
2044
|
connection.addListener("connect", handleConnect);
|
|
2041
2045
|
connection.addListener("connectFailed", handleConnectFailed);
|
|
2042
2046
|
});
|
|
2043
|
-
const connectionId = crypto.randomUUID();
|
|
2044
2047
|
const devSession = devOverlay ? `${baseQueue}#${createHash2("sha256").update(devOverlay).digest("hex").slice(0, 16)}` : "";
|
|
2045
2048
|
const backchannelQueue = `${queue}-backchannel-${connectionId}`;
|
|
2046
2049
|
const sentComponents = new Set;
|
|
@@ -2513,8 +2516,9 @@ function createConnection({
|
|
|
2513
2516
|
begin: true,
|
|
2514
2517
|
epoch,
|
|
2515
2518
|
...buildServiceIdentityHeaders({
|
|
2516
|
-
libVersion: "javascript@0.8.2-edge.
|
|
2517
|
-
name
|
|
2519
|
+
libVersion: "javascript@0.8.2-edge.1165",
|
|
2520
|
+
name,
|
|
2521
|
+
holdsSlot: !(isGeneratorHandler && mode === "CONTINUOUS")
|
|
2518
2522
|
})
|
|
2519
2523
|
});
|
|
2520
2524
|
if (isMessageHandlerGenerator(messageHandler)) {
|
|
@@ -3082,5 +3086,5 @@ export {
|
|
|
3082
3086
|
PayloadTooLargeError
|
|
3083
3087
|
};
|
|
3084
3088
|
|
|
3085
|
-
//# debugId=
|
|
3089
|
+
//# debugId=F491F98E2DCBAEE164756E2164756E21
|
|
3086
3090
|
//# sourceMappingURL=index.js.map
|