@znight/messaging 0.0.0-stage → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +622 -2
- package/dist/async-CFh_bvex.mjs +216 -0
- package/dist/async-CFh_bvex.mjs.map +1 -0
- package/dist/codec-Dku-NXXU.mjs +83 -0
- package/dist/codec-Dku-NXXU.mjs.map +1 -0
- package/dist/compiler.d.mts +75 -0
- package/dist/compiler.mjs +1023 -0
- package/dist/compiler.mjs.map +1 -0
- package/dist/driver-ZxLqy_Ap.d.mts +216 -0
- package/dist/index.d.mts +459 -0
- package/dist/index.mjs +870 -0
- package/dist/index.mjs.map +1 -0
- package/dist/kafka.d.mts +51 -0
- package/dist/kafka.mjs +517 -0
- package/dist/kafka.mjs.map +1 -0
- package/dist/memory.d.mts +124 -0
- package/dist/memory.mjs +429 -0
- package/dist/memory.mjs.map +1 -0
- package/dist/rabbitmq.d.mts +65 -0
- package/dist/rabbitmq.mjs +686 -0
- package/dist/rabbitmq.mjs.map +1 -0
- package/dist/shared-BJBpLS8V.mjs +52 -0
- package/dist/shared-BJBpLS8V.mjs.map +1 -0
- package/dist/sqs.d.mts +38 -0
- package/dist/sqs.mjs +421 -0
- package/dist/sqs.mjs.map +1 -0
- package/package.json +123 -4
- package/src/broker.ts +156 -0
- package/src/codec.ts +98 -0
- package/src/compiler/analyze.ts +800 -0
- package/src/compiler/constants.ts +73 -0
- package/src/compiler/data.ts +75 -0
- package/src/compiler/generate.ts +131 -0
- package/src/compiler/index.ts +52 -0
- package/src/compiler/patterns.ts +54 -0
- package/src/compiler/retry.ts +136 -0
- package/src/compiler/validate.ts +57 -0
- package/src/compiler/values.ts +76 -0
- package/src/consumers.ts +260 -0
- package/src/decorators.ts +131 -0
- package/src/driver.ts +142 -0
- package/src/drivers/kafka.ts +765 -0
- package/src/drivers/memory.ts +609 -0
- package/src/drivers/rabbitmq.ts +944 -0
- package/src/drivers/shared.ts +81 -0
- package/src/drivers/sqs.ts +583 -0
- package/src/errors.ts +95 -0
- package/src/headers.ts +70 -0
- package/src/hooks.ts +2 -0
- package/src/index.ts +89 -0
- package/src/internal/async.ts +115 -0
- package/src/message.ts +96 -0
- package/src/metadata.ts +65 -0
- package/src/plugin.ts +236 -0
- package/src/retry.ts +129 -0
- package/src/runtime.ts +424 -0
- package/src/standard-schema.ts +68 -0
- package/src/tokens.ts +14 -0
- package/src/validation.ts +61 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compiler.mjs","names":[],"sources":["../src/compiler/constants.ts","../src/compiler/patterns.ts","../src/compiler/values.ts","../src/compiler/retry.ts","../src/compiler/analyze.ts","../src/compiler/generate.ts","../src/compiler/validate.ts","../src/compiler/index.ts"],"sourcesContent":["/**\n * Constants shared by the compiler extension modules. This module must stay free of runtime imports:\n * the extension entry is loaded by the compiler, which must never load the messaging runtime (spec §2).\n */\nimport type { ErrorCode } from '@znight/core'\n\n/** Name of the extension, also the key of `metadata.extensions.messaging`. */\nexport const EXTENSION_NAME = 'messaging'\n\n/** Module the generated code imports its helpers and types from. */\nexport const RUNTIME_MODULE = '@znight/messaging'\n\n/** Canonical identities of the decorators owned by the extension. */\nexport const MessagingDecorator: {\n readonly Consumer: '@znight/messaging#Consumer'\n readonly OnMessage: '@znight/messaging#OnMessage'\n readonly Retry: '@znight/messaging#Retry'\n readonly OnError: '@znight/messaging#OnError'\n readonly Message: '@znight/messaging#Message'\n readonly Headers: '@znight/messaging#Headers'\n readonly Ctx: '@znight/messaging#Ctx'\n} = Object.freeze({\n Consumer: '@znight/messaging#Consumer',\n OnMessage: '@znight/messaging#OnMessage',\n Retry: '@znight/messaging#Retry',\n OnError: '@znight/messaging#OnError',\n Message: '@znight/messaging#Message',\n Headers: '@znight/messaging#Headers',\n Ctx: '@znight/messaging#Ctx',\n})\n\n/** Identity of the `InboundMessage` interface (`@Ctx()` parameters). */\nexport const INBOUND_MESSAGE_IDENTITY = '@znight/messaging#InboundMessage'\n\n/** Decorators applied to methods. */\nexport const METHOD_DECORATORS: ReadonlySet<string> = new Set([\n MessagingDecorator.OnMessage,\n MessagingDecorator.Retry,\n MessagingDecorator.OnError,\n])\n\n/** Decorators applied to handler parameters. */\nexport const PARAMETER_DECORATORS: ReadonlySet<string> = new Set([\n MessagingDecorator.Message,\n MessagingDecorator.Headers,\n MessagingDecorator.Ctx,\n])\n\n/** ZNIGHT005: invalid decorator usage (target, arguments, several decorators...). */\nexport const INVALID_DECORATOR: ErrorCode = 'ZNIGHT005'\n/** ZNIGHT011: invalid message consumer (no handler, overlapping types, retry options...). */\nexport const INVALID_CONSUMER: ErrorCode = 'ZNIGHT011'\n/** ZNIGHT017: non-primitive `@Message()` payload without schema. */\nexport const UNVALIDATED_INPUT: ErrorCode = 'ZNIGHT017'\n\n/**\n * Default backoff of `@Retry` (must equal the runtime `DEFAULT_BACKOFF`; checked by the tests, the\n * runtime module cannot be imported here).\n */\nexport const DEFAULT_BACKOFF = 'exponential'\n/** Default base delay of `@Retry`, in milliseconds (the runtime `DEFAULT_RETRY_DELAY_MS`). */\nexport const DEFAULT_RETRY_DELAY_MS = 1000\n/** Largest `attempts` accepted by the runtime (`normalizeRetry`). */\nexport const MAX_RETRY_ATTEMPTS = 10_000\n\n/** Scopes a consumer provider may have. */\nexport const CONSUMER_SCOPES: readonly string[] = ['singleton', 'request', 'transient']\n\n/** Deterministic string comparison (never `localeCompare`). */\nexport function compareStrings(a: string, b: string): number {\n if (a === b) return 0\n return a < b ? -1 : 1\n}\n","/**\n * Message type patterns of `@OnMessage(type)`, with the semantics of the runtime handler selection\n * (`consumers.ts`): a type containing `*` is a pattern where `*` matches any sequence of characters;\n * any other type is matched exactly. Exact types are tried first, then patterns in declaration order.\n */\n\n/** Whether `type` is a pattern (contains `*`). */\nexport function isPattern(type: string): boolean {\n return type.includes('*')\n}\n\n/** Whether `type` matches `pattern` (`*` matches any sequence of characters, the runtime semantics). */\nexport function matchesPattern(pattern: string, type: string): boolean {\n return covers(pattern, type, false)\n}\n\n/**\n * Whether every message type matched by `inner` is also matched by `outer`, so that `inner`, tried\n * after `outer`, can never be selected. The check is sound (never reports a pattern that can be\n * selected): `outer` must match `inner` where each `*` of `inner` can only be consumed by a `*` of\n * `outer`.\n */\nexport function patternCovers(outer: string, inner: string): boolean {\n return covers(outer, inner, true)\n}\n\n/** Glob matching of `subject` by `pattern`; with `starsAreWildcards`, `*` of `subject` only match `*` of `pattern`. */\nfunction covers(pattern: string, subject: string, starsAreWildcards: boolean): boolean {\n const p = collapseStars(pattern)\n const s = starsAreWildcards ? collapseStars(subject) : subject\n // previous[j]: p[0, i - 1) matches s[0, j)\n let previous: boolean[] = new Array<boolean>(s.length + 1).fill(false)\n previous[0] = true\n for (let i = 1; i <= p.length; i++) {\n const char = p[i - 1]\n const current: boolean[] = new Array<boolean>(s.length + 1).fill(false)\n current[0] = char === '*' && previous[0] === true\n for (let j = 1; j <= s.length; j++) {\n if (char === '*') {\n current[j] = previous[j] === true || current[j - 1] === true\n } else {\n const subjectChar = s[j - 1]\n current[j] = previous[j - 1] === true && subjectChar === char && !(starsAreWildcards && subjectChar === '*')\n }\n }\n previous = current\n }\n return previous[s.length] === true\n}\n\n/** `a**b` → `a*b` (same language). */\nfunction collapseStars(pattern: string): string {\n return pattern.replace(/\\*{2,}/g, '*')\n}\n","/**\n * Helpers on statically evaluated decorator arguments and their source locations.\n */\nimport type { ArgInfo, Location, Project, StaticValue } from '@znight/compiler'\n\ntype Expression = ArgInfo['node']\n\n/** An evaluated object literal (not an array, not a reference to an exported binding). */\nexport function isRecord(value: StaticValue): value is Readonly<Record<string, StaticValue>> {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return false\n const prototype: unknown = Object.getPrototypeOf(value)\n return prototype === Object.prototype || prototype === null\n}\n\n/** Short description of a value for messages (`\"orders\"`, `42`, `an array`...). */\nexport function describeValue(value: StaticValue): string {\n if (value === undefined) return 'undefined'\n if (value === null) return 'null'\n if (typeof value === 'string') return JSON.stringify(value)\n if (typeof value === 'bigint') return `${value}n`\n if (typeof value !== 'object') return String(value)\n if (Array.isArray(value)) return 'an array'\n return isRecord(value) ? 'an object' : `a reference to '${(value as { readonly text?: string }).text ?? '?'}'`\n}\n\n/**\n * Location of the property `key` of an object literal argument (`attempts: 0` in\n * `@Retry({ attempts: 0 })`), or of the whole argument when it is not an inline object literal.\n */\nexport function propertyLocation(project: Project, arg: ArgInfo, key: string): Location {\n let node: Expression = arg.node\n while (\n node.type === 'TSAsExpression' ||\n node.type === 'TSSatisfiesExpression' ||\n node.type === 'TSNonNullExpression' ||\n node.type === 'ParenthesizedExpression'\n ) {\n node = node.expression\n }\n if (node.type !== 'ObjectExpression') return arg.location\n for (const property of node.properties) {\n if (property.type !== 'Property' || property.computed) continue\n const { key: name } = property\n const found =\n name.type === 'Identifier' ? name.name : name.type === 'Literal' && typeof name.value === 'string' && name.value\n if (found === key) return project.getFile(arg.location.file)?.location(property) ?? arg.location\n }\n return arg.location\n}\n\n/** Closest candidate of `name` among `candidates` (typos: `attempt` → `attempts`), if any. */\nexport function closest(name: string, candidates: readonly string[]): string | undefined {\n let best: string | undefined\n let bestDistance = Math.max(2, Math.floor(name.length / 3)) + 1\n for (const candidate of candidates) {\n const distance = editDistance(name.toLowerCase(), candidate.toLowerCase())\n if (distance < bestDistance) {\n best = candidate\n bestDistance = distance\n }\n }\n return best\n}\n\nfunction editDistance(a: string, b: string): number {\n let previous = Array.from({ length: b.length + 1 }, (_, index) => index)\n for (let i = 1; i <= a.length; i++) {\n const current = [i]\n for (let j = 1; j <= b.length; j++) {\n const substitution = (previous[j - 1] ?? 0) + (a[i - 1] === b[j - 1] ? 0 : 1)\n current[j] = Math.min((previous[j] ?? 0) + 1, (current[j - 1] ?? 0) + 1, substitution)\n }\n previous = current\n }\n return previous[b.length] ?? 0\n}\n","/**\n * Compile-time validation and normalization of `@Retry` options. Mirrors the runtime\n * `normalizeRetry()` (same rules and defaults) so that invalid policies fail the build instead of the\n * boot; it also rejects unknown options (typos) and warns about options without effect.\n */\nimport type { AnalyzeContext, DecoratorInfo, StaticValue } from '@znight/compiler'\nimport type { MessagingData, RetryPolicyData } from './data.ts'\n\nimport {\n DEFAULT_BACKOFF,\n DEFAULT_RETRY_DELAY_MS,\n INVALID_CONSUMER,\n INVALID_DECORATOR,\n MAX_RETRY_ATTEMPTS,\n} from './constants.ts'\nimport { closest, describeValue, isRecord, propertyLocation } from './values.ts'\n\nconst RETRY_OPTIONS: readonly string[] = ['attempts', 'backoff', 'delay', 'maxDelay']\n\n/**\n * Validates the argument of a `@Retry` decorator and fills the runtime defaults. Returns `undefined`\n * (after reporting the problems) when the options are invalid.\n *\n * @param where the handler (`OrderConsumer.placed()`), used in messages\n */\nexport function normalizeRetryDecorator(\n decorator: DecoratorInfo,\n where: string,\n ctx: AnalyzeContext<MessagingData>,\n): RetryPolicyData | undefined {\n if (!decorator.called) return undefined // `@Retry` without call: already reported\n const arg = decorator.args[0]\n if (arg === undefined) {\n ctx.report({\n code: INVALID_DECORATOR,\n severity: 'error',\n message: `@Retry on ${where} requires options: @Retry({ attempts: 3 })`,\n location: decorator.location,\n hints: ['attempts counts the first delivery: { attempts: 3 } means 1 delivery + 2 retries'],\n })\n return undefined\n }\n if (!arg.evaluated) return undefined // not statically evaluable: already reported\n const options = arg.value\n if (!isRecord(options)) {\n ctx.report({\n code: INVALID_DECORATOR,\n severity: 'error',\n message: `@Retry on ${where} expects an options object ({ attempts, backoff?, delay?, maxDelay? }), got ${describeValue(options)}`,\n location: arg.location,\n })\n return undefined\n }\n\n let valid = true\n const fail = (key: string, message: string, hints?: readonly string[]): void => {\n valid = false\n ctx.report({\n code: INVALID_CONSUMER,\n severity: 'error',\n message: `@Retry on ${where}: ${message}`,\n location: propertyLocation(ctx.project, arg, key),\n ...(hints === undefined ? {} : { hints }),\n })\n }\n\n for (const key of Object.keys(options)) {\n if (RETRY_OPTIONS.includes(key)) continue\n const suggestion = closest(key, RETRY_OPTIONS)\n fail(key, `unknown option \"${key}\"`, [\n suggestion === undefined\n ? `Valid options: ${RETRY_OPTIONS.join(', ')}`\n : `Did you mean \"${suggestion}\"? Valid options: ${RETRY_OPTIONS.join(', ')}`,\n ])\n }\n\n const attempts = options['attempts']\n if (attempts === undefined) {\n fail('attempts', '\"attempts\" is required', [\n 'attempts counts the first delivery: { attempts: 3 } means 1 delivery + 2 retries',\n ])\n } else if (!isInteger(attempts) || attempts < 1 || attempts > MAX_RETRY_ATTEMPTS) {\n fail(\n 'attempts',\n `\"attempts\" must be an integer between 1 and ${MAX_RETRY_ATTEMPTS}, got ${describeValue(attempts)}`,\n ['attempts counts the first delivery: { attempts: 3 } means 1 delivery + 2 retries'],\n )\n }\n\n const rawBackoff = options['backoff']\n const backoff = rawBackoff === undefined ? DEFAULT_BACKOFF : rawBackoff\n if (backoff !== 'fixed' && backoff !== 'exponential') {\n fail('backoff', `\"backoff\" must be 'fixed' or 'exponential', got ${describeValue(backoff)}`)\n }\n\n const rawDelay = options['delay']\n const delay = rawDelay === undefined ? DEFAULT_RETRY_DELAY_MS : rawDelay\n const delayValid = isDuration(delay)\n if (!delayValid) {\n fail('delay', `\"delay\" must be a finite number of milliseconds >= 0, got ${describeValue(delay)}`)\n }\n\n const maxDelay = options['maxDelay']\n if (maxDelay !== undefined) {\n if (!isDuration(maxDelay) || (delayValid && maxDelay < delay)) {\n fail(\n 'maxDelay',\n `\"maxDelay\" must be a finite number of milliseconds >= delay${delayValid ? ` (${delay})` : ''}, got ${describeValue(maxDelay)}`,\n )\n } else if (backoff === 'fixed') {\n ctx.report({\n code: INVALID_CONSUMER,\n severity: 'warning',\n message: `@Retry on ${where}: \"maxDelay\" has no effect with backoff 'fixed' (every retry waits \"delay\")`,\n location: propertyLocation(ctx.project, arg, 'maxDelay'),\n hints: [\"Remove maxDelay, or use backoff: 'exponential'\"],\n })\n }\n }\n\n if (!valid || !isInteger(attempts) || (backoff !== 'fixed' && backoff !== 'exponential') || !isDuration(delay)) {\n return undefined\n }\n const policy: RetryPolicyData = isDuration(maxDelay)\n ? { attempts, backoff, delay, maxDelay }\n : { attempts, backoff, delay }\n return Object.freeze(policy)\n}\n\nfunction isInteger(value: StaticValue): value is number {\n return typeof value === 'number' && Number.isInteger(value)\n}\n\nfunction isDuration(value: StaticValue): value is number {\n return typeof value === 'number' && Number.isFinite(value) && value >= 0\n}\n","/**\n * `analyzeClass` of the messaging extension: reads `@Consumer` classes, their `@OnMessage` handlers\n * (`@Retry`, parameters), their `@OnError` method, registers the consumer provider and reports every\n * problem that can be detected on one class (ZNIGHT005, ZNIGHT011, ZNIGHT017).\n *\n * Handlers may be declared on base classes: the consumer inherits the messaging methods of its\n * analysable base classes (the nearest declaration of a method carrying messaging decorators wins, an\n * override without decorators keeps the inherited handler).\n */\nimport type {\n AnalyzeContext,\n ClassInfo,\n DecoratorInfo,\n Location,\n MethodInfo,\n ParameterInfo,\n StaticValue,\n TypeHelpers,\n TypeInfo,\n ValueRef,\n} from '@znight/compiler'\nimport type { Scope } from '@znight/core'\nimport type { HandlerData, HandlerParamData, MessagingData, RetryPolicyData } from './data.ts'\n\nimport {\n CONSUMER_SCOPES,\n EXTENSION_NAME,\n INBOUND_MESSAGE_IDENTITY,\n INVALID_CONSUMER,\n INVALID_DECORATOR,\n METHOD_DECORATORS,\n MessagingDecorator,\n PARAMETER_DECORATORS,\n RUNTIME_MODULE,\n UNVALIDATED_INPUT,\n} from './constants.ts'\nimport { isPattern, patternCovers } from './patterns.ts'\nimport { normalizeRetryDecorator } from './retry.ts'\nimport { describeValue, isRecord, propertyLocation } from './values.ts'\n\ntype Context = AnalyzeContext<MessagingData>\n\n/** The messaging declarations of one method. */\ninterface MemberAnalysis {\n readonly method: string\n readonly declaredBy: string\n /** Number of `@OnMessage` decorators (valid or not). */\n readonly onMessage: number\n /** One entry per valid `@OnMessage` decorator. */\n readonly handlers: readonly HandlerData[]\n /** Location of the `@OnError` decorator when the method is the error handler. */\n readonly errorHandler: Location | undefined\n}\n\n/** Types injected as is by `@Message()` without being \"unvalidated input\" (binary payloads). */\nconst BINARY_TYPES: ReadonlySet<string> = new Set([\n 'globalThis#Uint8Array',\n 'globalThis#ArrayBuffer',\n 'globalThis#Buffer',\n 'node:buffer#Buffer',\n 'buffer#Buffer',\n])\n\n/** Maximum depth of the base class chain walked for inherited handlers. */\nconst MAX_CHAIN = 32\n\n/** Analyses a class carrying at least one decorator of the extension. */\nexport function analyzeMessagingClass(cls: ClassInfo, ctx: Context): void {\n const own = analyzeMembers(cls, ctx)\n const consumers = cls.decorators.filter(decorator => decorator.identity === MessagingDecorator.Consumer)\n const consumer = consumers[0]\n if (consumer === undefined) {\n const decorators = cls.methods.flatMap(method =>\n method.decorators\n .filter(decorator => decorator.identity !== undefined && METHOD_DECORATORS.has(decorator.identity))\n .map(decorator => ({ name: decorator.name, location: decorator.location })),\n )\n if (decorators.length > 0) {\n ctx.store({\n kind: 'members',\n identity: cls.identity,\n displayName: cls.displayName,\n abstract: cls.abstract,\n decorators,\n })\n }\n return\n }\n for (const duplicate of consumers.slice(1)) {\n ctx.report({\n code: INVALID_DECORATOR,\n severity: 'error',\n message: `@${duplicate.name} is applied several times on ${cls.displayName}`,\n location: duplicate.location,\n hints: [`Keep a single @${duplicate.name}: a class consumes one queue`],\n })\n }\n\n const options = readConsumerOptions(consumer, cls, ctx)\n const token = ctx.registerProvider(cls, { scope: options.scope })\n const chain = classChain(cls, ctx)\n\n // messaging methods of the class and its bases: the nearest declaration wins, at the position of\n // the first declaration (base classes first)\n const merged = new Map<string, MemberAnalysis>()\n for (let index = chain.length - 1; index >= 0; index--) {\n const owner = chain[index] as ClassInfo\n for (const [name, member] of index === 0 ? own : analyzeMembers(owner, ctx)) merged.set(name, member)\n }\n const members = [...merged.values()]\n const handlers = members.flatMap(member => member.handlers)\n\n if (!members.some(member => member.onMessage > 0)) {\n ctx.report({\n code: INVALID_CONSUMER,\n severity: 'error',\n message: `@Consumer ${cls.displayName} has no @OnMessage handler`,\n location: consumer.location,\n hints: ['Decorate at least one public method with @OnMessage() (default handler) or @OnMessage(\"type\")'],\n })\n }\n checkHandlerTypes(cls.displayName, handlers, ctx)\n\n const errorHandlers = members.filter(member => member.errorHandler !== undefined)\n const errorHandler = errorHandlers[0]\n for (const extra of errorHandlers.slice(1)) {\n ctx.report({\n code: INVALID_CONSUMER,\n severity: 'error',\n message: `@Consumer ${cls.displayName} has several @OnError methods: ${errorHandlers.map(member => `${member.declaredBy}.${member.method}()`).join(', ')}`,\n location: extra.errorHandler as Location,\n hints: ['Keep a single @OnError method per consumer'],\n related: [{ message: 'First @OnError method', location: errorHandler?.errorHandler as Location }],\n })\n }\n\n ctx.store({\n kind: 'consumer',\n token,\n identity: cls.identity,\n displayName: cls.displayName,\n queue: options.queue,\n options: options.options,\n handlers,\n errorHandler: errorHandler?.method,\n chain: chain.map(owner => owner.identity),\n location: consumer.location,\n })\n}\n\n// ------------------------------------------------------------------------------------------ consumer\n\ninterface ConsumerOptions {\n /** Empty when invalid (reported). */\n readonly queue: string\n readonly scope: Scope\n readonly options: Readonly<Record<string, StaticValue>> | undefined\n}\n\n/** `@Consumer(queue)` / `@Consumer({ queue, scope?, concurrency?, deadLetter?, ...driver options })`. */\nfunction readConsumerOptions(decorator: DecoratorInfo, cls: ClassInfo, ctx: Context): ConsumerOptions {\n const invalid: ConsumerOptions = { queue: '', scope: 'singleton', options: undefined }\n const prefix = `@Consumer ${cls.displayName}`\n if (!decorator.called) return invalid // `@Consumer` without call: already reported\n const arg = decorator.args[0]\n if (arg === undefined) {\n ctx.report({\n code: INVALID_DECORATOR,\n severity: 'error',\n message: `${prefix}: the queue to consume is required`,\n location: decorator.location,\n hints: [\"Write @Consumer('orders') or @Consumer({ queue: 'orders', concurrency: 5 })\"],\n })\n return invalid\n }\n if (!arg.evaluated) return invalid // not statically evaluable: already reported\n const value = arg.value\n if (typeof value === 'string') {\n if (value === '') {\n ctx.report({\n code: INVALID_CONSUMER,\n severity: 'error',\n message: `${prefix}: the queue must be a non-empty string`,\n location: arg.location,\n })\n }\n return { queue: value, scope: 'singleton', options: undefined }\n }\n if (!isRecord(value)) {\n ctx.report({\n code: INVALID_DECORATOR,\n severity: 'error',\n message: `${prefix}: expected a queue name or an options object ({ queue, scope?, concurrency?, deadLetter? }), got ${describeValue(value)}`,\n location: arg.location,\n })\n return invalid\n }\n\n const fail = (key: string, message: string, hints?: readonly string[]): void => {\n ctx.report({\n code: INVALID_CONSUMER,\n severity: 'error',\n message: `${prefix}: ${message}`,\n location: propertyLocation(ctx.project, arg, key),\n ...(hints === undefined ? {} : { hints }),\n })\n }\n\n let queue = ''\n const rawQueue = value['queue']\n if (rawQueue === undefined) {\n fail('queue', 'the \"queue\" option is required', [\"Write @Consumer({ queue: 'orders', ... })\"])\n } else if (typeof rawQueue !== 'string' || rawQueue === '') {\n fail('queue', `\"queue\" must be a non-empty string, got ${describeValue(rawQueue)}`)\n } else {\n queue = rawQueue\n }\n\n let scope: Scope = 'singleton'\n const rawScope = value['scope']\n if (rawScope !== undefined) {\n if (typeof rawScope === 'string' && CONSUMER_SCOPES.includes(rawScope)) {\n scope = rawScope as Scope\n } else {\n fail('scope', `\"scope\" must be 'singleton', 'request' or 'transient', got ${describeValue(rawScope)}`)\n }\n }\n\n const concurrency = value['concurrency']\n if (\n concurrency !== undefined &&\n !(typeof concurrency === 'number' && Number.isSafeInteger(concurrency) && concurrency > 0)\n ) {\n fail('concurrency', `\"concurrency\" must be a positive integer, got ${describeValue(concurrency)}`)\n }\n\n const deadLetter = value['deadLetter']\n if (deadLetter !== undefined && deadLetter !== false && (typeof deadLetter !== 'string' || deadLetter === '')) {\n fail('deadLetter', `\"deadLetter\" must be a queue name or false, got ${describeValue(deadLetter)}`)\n } else if (deadLetter === queue && queue !== '') {\n fail('deadLetter', `the dead-letter queue cannot be the consumed queue \"${queue}\"`, [\n 'Use another queue (default: the driver naming, e.g. \"orders.dlq\"), or false to disable dead-lettering',\n ])\n }\n\n const options: Record<string, StaticValue> = {}\n for (const [key, option] of Object.entries(value)) {\n if (key === 'queue' || key === 'scope' || option === undefined) continue\n options[key] = option\n }\n return { queue, scope, options: Object.keys(options).length === 0 ? undefined : Object.freeze(options) }\n}\n\n/** The class and its analysable base classes (nearest first). */\nfunction classChain(cls: ClassInfo, ctx: Context): ClassInfo[] {\n const chain = [cls]\n const seen = new Set([cls.identity])\n let current = cls\n while (current.superClass !== undefined && chain.length < MAX_CHAIN) {\n const base = ctx.classInfo(current.superClass.identity)\n if (base === undefined || seen.has(base.identity)) break\n chain.push(base)\n seen.add(base.identity)\n current = base\n }\n return chain\n}\n\n/**\n * Handler selection checks, mirroring the runtime (`consumers.ts`): exact types first, then patterns\n * in declaration order, then the single default handler.\n */\nfunction checkHandlerTypes(consumer: string, handlers: readonly HandlerData[], ctx: Context): void {\n let fallback: HandlerData | undefined\n const exact = new Map<string, HandlerData>()\n const patterns: (HandlerData & { readonly type: string })[] = []\n const label = (handler: HandlerData): string => `${handler.declaredBy}.${handler.method}()`\n for (const handler of handlers) {\n const type = handler.type\n if (type === undefined) {\n if (fallback === undefined) {\n fallback = handler\n continue\n }\n ctx.report({\n code: INVALID_CONSUMER,\n severity: 'error',\n message: `@Consumer ${consumer}: ${label(fallback)} and ${label(handler)} are both default @OnMessage() handlers`,\n location: handler.location,\n hints: ['Give one of them a message type: @OnMessage(\"order.created\")'],\n related: [{ message: 'First default handler', location: fallback.location }],\n })\n continue\n }\n const previous = isPattern(type) ? patterns.find(pattern => pattern.type === type) : exact.get(type)\n if (previous !== undefined) {\n ctx.report({\n code: INVALID_CONSUMER,\n severity: 'error',\n message: `@Consumer ${consumer}: several @OnMessage handlers for type \"${type}\" (${label(previous)} and ${label(handler)})`,\n location: handler.location,\n hints: ['A message type is handled by a single method: merge the handlers'],\n related: [{ message: `First handler of \"${type}\"`, location: previous.location }],\n })\n continue\n }\n if (!isPattern(type)) {\n exact.set(type, handler)\n continue\n }\n const covering = patterns.find(pattern => patternCovers(pattern.type, type))\n if (covering !== undefined) {\n ctx.report({\n code: INVALID_CONSUMER,\n severity: 'error',\n message: `@Consumer ${consumer}: the pattern \"${type}\" of ${label(handler)} never matches: every type it matches is matched first by \"${covering.type}\" (${label(covering)})`,\n location: handler.location,\n hints: ['Patterns are tried in declaration order (after exact types): declare the more specific pattern first'],\n related: [{ message: `Pattern \"${covering.type}\"`, location: covering.location }],\n })\n }\n patterns.push({ ...handler, type })\n }\n}\n\n// ------------------------------------------------------------------------------------------- members\n\n/** Messaging methods declared by `cls` itself, by name, in declaration order. */\nfunction analyzeMembers(cls: ClassInfo, ctx: Context): Map<string, MemberAnalysis> {\n const members = new Map<string, MemberAnalysis>()\n for (const method of cls.methods) {\n const member = analyzeMethod(cls, method, ctx)\n if (member !== undefined) members.set(method.name, member)\n }\n return members\n}\n\nfunction analyzeMethod(cls: ClassInfo, method: MethodInfo, ctx: Context): MemberAnalysis | undefined {\n const onMessage = decoratorsOf(method.decorators, MessagingDecorator.OnMessage)\n const retry = decoratorsOf(method.decorators, MessagingDecorator.Retry)\n const onError = decoratorsOf(method.decorators, MessagingDecorator.OnError)\n const decoratedParams = method.params.some(param => param.decorators.some(isParameterDecorator))\n if (onMessage.length === 0 && retry.length === 0 && onError.length === 0 && !decoratedParams) return undefined\n\n const where = `${cls.displayName}.${method.name}()`\n const primary = onMessage[0] ?? onError[0]\n if (primary !== undefined) checkMethodShape(method, primary, where, ctx)\n for (const duplicate of [...retry.slice(1), ...onError.slice(1)]) {\n ctx.report({\n code: INVALID_DECORATOR,\n severity: 'error',\n message: `@${duplicate.name} is applied several times on ${where}`,\n location: duplicate.location,\n hints: [`Keep a single @${duplicate.name}`],\n })\n }\n if (onMessage.length > 0 && onError[0] !== undefined) {\n ctx.report({\n code: INVALID_DECORATOR,\n severity: 'error',\n message: `${where} cannot be both an @OnMessage handler and the @OnError method`,\n location: onError[0].location,\n hints: ['Declare the error handler in a separate method'],\n })\n }\n if (onMessage.length === 0 && retry[0] !== undefined) {\n ctx.report({\n code: INVALID_DECORATOR,\n severity: 'error',\n message: `@Retry has no effect on ${where}: it is not an @OnMessage handler`,\n location: retry[0].location,\n hints: ['Add @OnMessage() to the method, or remove @Retry'],\n })\n }\n\n let handlers: HandlerData[] = []\n if (onMessage.length > 0) {\n const policy: RetryPolicyData | undefined =\n retry[0] === undefined ? undefined : normalizeRetryDecorator(retry[0], where, ctx)\n const params = analyzeHandlerParams(method, where, ctx)\n handlers = onMessage.flatMap(decorator => {\n const type = messageType(decorator, where, ctx)\n if (type === false) return []\n return [\n Object.freeze({\n method: method.name,\n type,\n retry: policy,\n params,\n declaredBy: cls.displayName,\n location: decorator.location,\n }),\n ]\n })\n } else {\n reportStrayParameterDecorators(method, where, onError.length > 0, ctx)\n }\n\n const errorHandler = onMessage.length === 0 ? onError[0] : undefined\n if (errorHandler !== undefined) checkErrorHandler(method, errorHandler, where, ctx)\n return {\n method: method.name,\n declaredBy: cls.displayName,\n onMessage: onMessage.length,\n handlers,\n errorHandler: errorHandler?.location,\n }\n}\n\n/** Handlers are called by the generated code: `consumer.method(...)`. */\nfunction checkMethodShape(method: MethodInfo, decorator: DecoratorInfo, where: string, ctx: Context): void {\n const name = `@${decorator.name}`\n let problem: { message: string; hint: string } | undefined\n if (method.kind !== 'method') {\n problem = { message: `${name} cannot be applied to the accessor ${where}`, hint: 'Use a regular method' }\n } else if (method.static) {\n problem = {\n message: `${name} cannot be applied to the static method ${where}`,\n hint: 'Handlers are called on the consumer instance: remove `static`',\n }\n } else if (method.privateName) {\n problem = {\n message: `${name} cannot be applied to the #private method ${where}`,\n hint: 'Use a public method: the generated code calls it',\n }\n } else if (method.visibility !== 'public') {\n problem = {\n message: `${where} must be public: ${name} methods are called by the generated code`,\n hint: `Remove the '${method.visibility}' modifier`,\n }\n } else if (method.computed) {\n problem = {\n message: `${name} cannot be applied to ${where}: computed method names are not supported`,\n hint: 'Use a plain method name',\n }\n } else if (method.generator) {\n problem = {\n message: `${name} cannot be applied to the generator method ${where}`,\n hint: 'Use a regular (or async) method',\n }\n }\n if (problem !== undefined) {\n ctx.report({\n code: INVALID_DECORATOR,\n severity: 'error',\n message: problem.message,\n location: decorator.location,\n hints: [problem.hint],\n })\n }\n}\n\n/** Type of an `@OnMessage` decorator: a string, `undefined` (default handler) or `false` (invalid). */\nfunction messageType(decorator: DecoratorInfo, where: string, ctx: Context): string | undefined | false {\n const arg = decorator.args[0]\n if (arg === undefined || (arg.evaluated && arg.value === undefined)) return undefined\n if (!arg.evaluated) return false // not statically evaluable: already reported\n if (typeof arg.value !== 'string') {\n ctx.report({\n code: INVALID_DECORATOR,\n severity: 'error',\n message: `@OnMessage on ${where} expects a message type (a string), got ${describeValue(arg.value)}`,\n location: arg.location,\n hints: ['Use @OnMessage() for the default handler'],\n })\n return false\n }\n if (arg.value === '') {\n ctx.report({\n code: INVALID_CONSUMER,\n severity: 'error',\n message: `The @OnMessage type of ${where} must be a non-empty string`,\n location: arg.location,\n hints: ['Use @OnMessage() for the default handler'],\n })\n return false\n }\n return arg.value\n}\n\n/** The `@OnError` method is called as `consumer[method](error, message)`. */\nfunction checkErrorHandler(method: MethodInfo, decorator: DecoratorInfo, where: string, ctx: Context): void {\n const required = method.params.filter(param => !param.optional && !param.hasDefault && !param.rest).length\n if (required > 2) {\n ctx.report({\n code: INVALID_CONSUMER,\n severity: 'error',\n message: `The @OnError method ${where} has ${required} required parameters: it is called with (error, message)`,\n location: method.location,\n hints: ['Declare onError(error: unknown, message: InboundMessage)'],\n })\n }\n if (method.returnType !== undefined && !isErrorHandlerResult(ctx.types.awaited(method.returnType))) {\n ctx.report({\n code: INVALID_CONSUMER,\n severity: 'error',\n message: `The @OnError method ${where} returns '${ctx.types.format(method.returnType)}': return 'ack' to acknowledge the message, or nothing to dead-letter it`,\n location: decorator.location,\n hints: [\"Declare the return type `'ack' | undefined` (or `void`)\"],\n })\n }\n}\n\n// ---------------------------------------------------------------------------------------- parameters\n\nfunction analyzeHandlerParams(method: MethodInfo, where: string, ctx: Context): readonly HandlerParamData[] {\n return Object.freeze(method.params.map(param => analyzeHandlerParam(param, where, ctx)))\n}\n\nfunction analyzeHandlerParam(param: ParameterInfo, where: string, ctx: Context): HandlerParamData {\n const decorators = parameterDecorators(param)\n const decorator = decorators[0]\n if (decorator === undefined) {\n const foreign = foreignParameterDecorator(param)\n if (foreign !== undefined) {\n // e.g. `Headers` auto-imported from '@znight/http': one precise error instead of \"no decorator\"\n ctx.report({\n code: INVALID_DECORATOR,\n severity: 'error',\n message: `@${foreign.decorator.name} on parameter '${param.name}' of ${where} is imported from '${foreign.module}': @OnMessage handler parameters use ${foreign.name} from '${RUNTIME_MODULE}'`,\n location: foreign.decorator.location,\n hints: [`Import it from '${RUNTIME_MODULE}': import { ${foreign.name} } from '${RUNTIME_MODULE}'`],\n })\n return { kind: 'undefined' }\n }\n if (param.optional || param.hasDefault || param.rest) return { kind: 'undefined' }\n ctx.report({\n code: INVALID_CONSUMER,\n severity: 'error',\n message: `Parameter '${param.name}' of ${where} has no @Message(), @Headers() or @Ctx() decorator`,\n location: param.location,\n hints: [\n 'Every handler parameter is extracted from the message: @Message(schema?) for the payload, @Headers(name?) for the headers, @Ctx() for the InboundMessage',\n ],\n })\n return { kind: 'undefined' }\n }\n if (decorators.length > 1) {\n ctx.report({\n code: INVALID_DECORATOR,\n severity: 'error',\n message: `Parameter '${param.name}' of ${where} has several messaging decorators (${decorators.map(found => `@${found.name}`).join(', ')})`,\n location: (decorators[1] as DecoratorInfo).location,\n hints: ['Keep a single one'],\n })\n }\n if (param.rest) {\n ctx.report({\n code: INVALID_DECORATOR,\n severity: 'error',\n message: `@${decorator.name} cannot be applied to the rest parameter '...${param.name}' of ${where}`,\n location: decorator.location,\n })\n return { kind: 'undefined' }\n }\n switch (decorator.identity) {\n case MessagingDecorator.Message:\n return messageParam(param, decorator, where, ctx)\n case MessagingDecorator.Headers:\n return headersParam(param, decorator, where, ctx)\n default:\n return { kind: 'message', narrow: narrowsPayload(param.type, ctx.types) }\n }\n}\n\n/** `@Message()` / `@Message(schema)`. */\nfunction messageParam(param: ParameterInfo, decorator: DecoratorInfo, where: string, ctx: Context): HandlerParamData {\n const arg = decorator.args[0]\n if (arg === undefined || (arg.evaluated && arg.value === undefined)) {\n checkUnvalidated(param, decorator, where, ctx)\n return { kind: 'payload' }\n }\n if (arg.ref !== undefined) {\n if (isClassReference(arg.ref)) {\n ctx.report({\n code: INVALID_DECORATOR,\n severity: 'error',\n message: `@Message(${arg.text}) on ${where}: '${arg.ref.name}' is a class, not a Standard Schema`,\n location: arg.location,\n hints: [\n 'Pass a Standard Schema (Zod, Valibot, ArkType...): export const OrderPlaced = z.object({ ... })',\n 'Or inject the raw payload with @Message() and validate it in the handler',\n ],\n })\n return { kind: 'undefined' }\n }\n return { kind: 'validated', schema: arg.ref }\n }\n if (!arg.evaluated) return { kind: 'undefined' } // unexported or invalid reference: already reported\n ctx.report({\n code: INVALID_DECORATOR,\n severity: 'error',\n message: `@Message on ${where} expects a Standard Schema (Zod, Valibot, ArkType...), got ${describeValue(arg.value)}`,\n location: arg.location,\n hints: [\n 'Declare the schema with `export const OrderPlaced = z.object({ ... })` and pass it: @Message(OrderPlaced)',\n ],\n })\n return { kind: 'undefined' }\n}\n\n/** `@Headers()` / `@Headers(name)`. */\nfunction headersParam(param: ParameterInfo, decorator: DecoratorInfo, where: string, ctx: Context): HandlerParamData {\n const arg = decorator.args[0]\n if (arg === undefined || (arg.evaluated && arg.value === undefined)) return { kind: 'headers' }\n if (!arg.evaluated) return { kind: 'undefined' } // not statically evaluable: already reported\n const name = arg.value\n if (typeof name !== 'string' || name === '') {\n ctx.report({\n code: INVALID_DECORATOR,\n severity: 'error',\n message: `@Headers on ${where} expects a header name (a non-empty string), got ${describeValue(name)}`,\n location: arg.location,\n hints: ['Use @Headers() to inject every header'],\n })\n return { kind: 'undefined' }\n }\n if (!param.optional && !param.hasDefault && !acceptsUndefined(param.type)) {\n ctx.report({\n code: INVALID_DECORATOR,\n severity: 'warning',\n message: `@Headers(${JSON.stringify(name)}) injects 'string | undefined' (the header may be missing) but parameter '${param.name}' of ${where} is typed '${ctx.types.format(param.type)}'`,\n location: param.typeLocation,\n hints: [`Declare it '${param.name}?: string' or '${param.name}: string | undefined', or give it a default value`],\n })\n }\n return { kind: 'header', name }\n}\n\n/** ZNIGHT017: a structured payload injected without schema is trusted blindly. */\nfunction checkUnvalidated(param: ParameterInfo, decorator: DecoratorInfo, where: string, ctx: Context): void {\n const { type } = ctx.types.stripNullish(param.type)\n if (isSafePayloadType(type)) return\n const typed =\n type.kind === 'opaque' && type.reason === 'missing-annotation'\n ? 'has no type annotation'\n : `is typed '${ctx.types.format(param.type)}'`\n ctx.report({\n code: UNVALIDATED_INPUT,\n severity: ctx.options.strictValidation ? 'error' : 'warning',\n message: `Unvalidated message payload: parameter '${param.name}' of ${where} ${typed} but @Message() has no schema`,\n location: decorator.location,\n hints: [\n 'Validate it with a Standard Schema (Zod, Valibot, ArkType...): @Message(OrderPlaced)',\n \"Or declare the parameter as 'unknown' and check it in the handler\",\n ],\n })\n}\n\n/** Methods whose parameters carry messaging decorators without being `@OnMessage` handlers. */\nfunction reportStrayParameterDecorators(method: MethodInfo, where: string, errorHandler: boolean, ctx: Context): void {\n // a method handled by another extension (an HTTP route...): the decorator comes from the wrong package\n const owner = errorHandler ? undefined : foreignHandler(method)\n for (const param of method.params) {\n for (const decorator of parameterDecorators(param)) {\n let hint = 'Add @OnMessage() to the method, or remove the decorator'\n if (errorHandler) hint = '@OnError methods are called with (error, message): remove the decorator'\n else if (owner !== undefined) {\n hint = `${where} is a @${owner.decorator.name} handler: use the parameter decorators of '${owner.module}'`\n }\n ctx.report({\n code: INVALID_DECORATOR,\n severity: 'error',\n message:\n owner === undefined\n ? `@${decorator.name} has no effect on parameter '${param.name}' of ${where}: it is not an @OnMessage handler`\n : `@${decorator.name} (from '${RUNTIME_MODULE}') has no effect on parameter '${param.name}' of ${where}: it is not an @OnMessage handler`,\n location: decorator.location,\n hints: [hint],\n })\n }\n }\n}\n\n/** A decorator, with the module and the export name of its identity (`'@znight/http#Get'`). */\ninterface ForeignDecorator {\n readonly decorator: DecoratorInfo\n readonly module: string\n readonly name: string\n}\n\nfunction splitIdentity(decorator: DecoratorInfo): ForeignDecorator | undefined {\n const identity = decorator.identity\n const separator = identity?.lastIndexOf('#') ?? -1\n if (identity === undefined || separator <= 0) return undefined\n return { decorator, module: identity.slice(0, separator), name: identity.slice(separator + 1) }\n}\n\n/**\n * A parameter decorator named like a messaging one (`Headers`, `Ctx`, `Message`) but imported from\n * another package (`@znight/http` has `Headers` and `Ctx` too).\n */\nfunction foreignParameterDecorator(param: ParameterInfo): ForeignDecorator | undefined {\n for (const decorator of param.decorators) {\n const split = splitIdentity(decorator)\n if (split === undefined || split.module === RUNTIME_MODULE) continue\n if (PARAMETER_DECORATORS.has(`${RUNTIME_MODULE}#${split.name}`)) return split\n }\n return undefined\n}\n\n/** The decorator through which another extension handles the method (`@Get` of `@znight/http`...). */\nfunction foreignHandler(method: MethodInfo): ForeignDecorator | undefined {\n for (const decorator of method.decorators) {\n const owner = decorator.owner\n if (owner === undefined || owner === EXTENSION_NAME || owner === 'core' || owner === 'manifest') continue\n const split = splitIdentity(decorator)\n if (split !== undefined) return split\n }\n return undefined\n}\n\n// ------------------------------------------------------------------------------------------- helpers\n\nfunction decoratorsOf(decorators: readonly DecoratorInfo[], identity: string): DecoratorInfo[] {\n return decorators.filter(decorator => decorator.identity === identity)\n}\n\n/**\n * Messaging decorators of a parameter. De-duplicated by position: the compiler (0.1) reports the\n * decorators of a parameter with a default value (`@Headers('x') x = 'a'`) twice.\n */\nfunction parameterDecorators(param: ParameterInfo): DecoratorInfo[] {\n const seen = new Set<number>()\n return param.decorators.filter(decorator => {\n if (!isParameterDecorator(decorator) || seen.has(decorator.location.start)) return false\n seen.add(decorator.location.start)\n return true\n })\n}\n\nfunction isParameterDecorator(decorator: DecoratorInfo): boolean {\n return decorator.identity !== undefined && PARAMETER_DECORATORS.has(decorator.identity)\n}\n\n/** A reference to a class declaration (`@Message(OrderDto)`). */\nfunction isClassReference(ref: ValueRef): boolean {\n const symbol = ref.symbol\n return symbol.kind === 'declaration' && symbol.declaration.kind === 'class'\n}\n\n/** Primitive and binary payload types need no schema (`unknown` is honest, `any` is not). */\nfunction isSafePayloadType(type: TypeInfo): boolean {\n switch (type.kind) {\n case 'primitive':\n return type.name !== 'any' && type.name !== 'object'\n case 'literal':\n return true\n case 'union':\n return type.types.every(isSafePayloadType)\n case 'reference':\n return BINARY_TYPES.has(type.identity)\n default:\n return false\n }\n}\n\n/** Whether `undefined` is assignable to the type (unknown types are given the benefit of the doubt). */\nfunction acceptsUndefined(type: TypeInfo): boolean {\n switch (type.kind) {\n case 'primitive':\n return type.name === 'any' || type.name === 'unknown' || type.name === 'undefined' || type.name === 'void'\n case 'union':\n return type.types.some(acceptsUndefined)\n case 'opaque':\n case 'typeParameter':\n return true\n default:\n return false\n }\n}\n\n/** Valid results of an `@OnError` method: `'ack'`, nothing (`void`, `undefined`), or unknown types. */\nfunction isErrorHandlerResult(type: TypeInfo): boolean {\n switch (type.kind) {\n case 'primitive':\n return ['void', 'undefined', 'any', 'unknown', 'never'].includes(type.name)\n case 'literal':\n return type.value === 'ack'\n case 'union':\n return type.types.every(isErrorHandlerResult)\n case 'promise':\n return isErrorHandlerResult(type.inner)\n case 'opaque':\n case 'typeParameter':\n return true\n default:\n return false\n }\n}\n\n/** `@Ctx() message: InboundMessage<Order>` narrows the payload: the invoker casts `m`. */\nfunction narrowsPayload(type: TypeInfo, types: TypeHelpers): boolean {\n const { type: inner } = types.stripNullish(type)\n if (inner.kind !== 'reference' || inner.identity !== INBOUND_MESSAGE_IDENTITY) return false\n const payload = inner.typeArgs[0]\n return (\n payload !== undefined && !(payload.kind === 'primitive' && (payload.name === 'unknown' || payload.name === 'any'))\n )\n}\n","/**\n * `generate` of the messaging extension: `metadata.extensions.messaging` (README \"Compiler contract\",\n * spec §9.2). Consumers are sorted by token; handlers keep their declaration order.\n *\n * ```ts\n * {\n * consumers: [{\n * token: 'src/orders/order.consumer.ts#OrderConsumer',\n * queue: 'orders',\n * handlers: [{\n * method: 'placed',\n * type: 'order.placed',\n * retry: { attempts: 5, backoff: 'exponential', delay: 500, maxDelay: 30000 },\n * invoke: async (c: OrderConsumer, m: InboundMessage) => c.placed(await validateMessage(OrderPlaced, m.payload)),\n * }],\n * errorHandler: 'onError',\n * }],\n * }\n * ```\n */\nimport type { GenerateContext, GenInput, GenNode } from '@znight/compiler'\nimport type { ConsumerData, HandlerData, HandlerParamData, MessagingData } from './data.ts'\n\nimport { compareStrings, RUNTIME_MODULE } from './constants.ts'\n\ntype Context = GenerateContext<MessagingData>\n\n/**\n * Imports of the runtime helpers, created on first use only: an import the module does not use would\n * break `noUnusedLocals`.\n */\ninterface Helpers {\n inboundMessage(): GenNode\n validateMessage(): GenNode\n messageHeader(): GenNode\n}\n\n/** Builds the messaging section; `undefined` (no section) when the application has no consumer. */\nexport function generateMessaging(ctx: Context): GenNode | undefined {\n const consumers = ctx.stored\n .filter((data): data is ConsumerData => data.kind === 'consumer')\n .sort((a, b) => compareStrings(a.token, b.token))\n if (consumers.length === 0) return undefined\n const helpers = lazyHelpers(ctx)\n return ctx.obj([['consumers', ctx.arr(consumers.map(consumer => consumerNode(ctx, consumer, helpers)))]])\n}\n\nfunction consumerNode(ctx: Context, consumer: ConsumerData, helpers: Helpers): GenNode {\n let classType: GenNode | undefined\n const consumerType = (): GenNode => {\n classType ??= ctx.importType(consumer.identity)\n return classType\n }\n const entries: [string, GenInput][] = [\n ['token', consumer.token],\n ['queue', consumer.queue],\n ]\n if (consumer.options !== undefined) entries.push(['options', ctx.lit(consumer.options)])\n entries.push([\n 'handlers',\n ctx.arr(consumer.handlers.map(handler => handlerNode(ctx, handler, consumerType, helpers))),\n ])\n if (consumer.errorHandler !== undefined) entries.push(['errorHandler', consumer.errorHandler])\n return ctx.obj(entries)\n}\n\nfunction handlerNode(ctx: Context, handler: HandlerData, consumerType: () => GenNode, helpers: Helpers): GenNode {\n const entries: [string, GenInput][] = [['method', handler.method]]\n if (handler.type !== undefined) entries.push(['type', handler.type])\n if (handler.retry !== undefined) entries.push(['retry', ctx.lit({ ...handler.retry })])\n entries.push(['invoke', invokeNode(ctx, handler, consumerType, helpers)])\n return ctx.obj(entries)\n}\n\n/**\n * `(c: Consumer, m: InboundMessage) => c.method(...args)`, `async` only when it awaits a schema\n * validation. `m` is omitted when no argument uses it (`noUnusedParameters`).\n */\nfunction invokeNode(ctx: Context, handler: HandlerData, consumerType: () => GenNode, helpers: Helpers): GenNode {\n const params = [...handler.params]\n while (params.length > 0 && params[params.length - 1]?.kind === 'undefined') params.pop()\n if (params.length === 0) {\n return ctx.arrow([['c', consumerType()]], c => ctx.call(ctx.member(c, handler.method)))\n }\n return ctx.arrow(\n [\n ['c', consumerType()],\n ['m', helpers.inboundMessage()],\n ],\n (c, m) =>\n ctx.call(\n ctx.member(c, handler.method),\n params.map(param => argumentNode(ctx, param, m as GenNode, helpers)),\n ),\n { async: params.some(param => param.kind === 'validated') },\n )\n}\n\nfunction argumentNode(ctx: Context, param: HandlerParamData, m: GenNode, helpers: Helpers): GenNode {\n switch (param.kind) {\n case 'payload':\n return ctx.code`${ctx.member(m, 'payload')} as never`\n case 'validated':\n return ctx.code`await ${ctx.call(helpers.validateMessage(), [ctx.importValue(param.schema), ctx.member(m, 'payload')])}`\n case 'headers':\n return ctx.member(m, 'headers')\n case 'header':\n return ctx.call(helpers.messageHeader(), [m, param.name])\n case 'message':\n return param.narrow ? ctx.code`${m} as ${helpers.inboundMessage()}<never>` : m\n case 'undefined':\n return ctx.lit(undefined)\n }\n}\n\nfunction lazyHelpers(ctx: Context): Helpers {\n const cache = new Map<string, GenNode>()\n const get = (name: string, type: boolean): GenNode => {\n let node = cache.get(name)\n if (node === undefined) {\n node = ctx.importFrom(RUNTIME_MODULE, name, type ? { type: true } : {})\n cache.set(name, node)\n }\n return node\n }\n return {\n inboundMessage: () => get('InboundMessage', true),\n validateMessage: () => get('validateMessage', false),\n messageHeader: () => get('messageHeader', false),\n }\n}\n","/**\n * `validate` of the messaging extension: checks that need every consumer of the application.\n */\nimport type { ValidateContext } from '@znight/compiler'\nimport type { ConsumerData, MemberClassData, MessagingData } from './data.ts'\n\nimport { compareStrings, INVALID_CONSUMER, INVALID_DECORATOR } from './constants.ts'\n\n/** Cross-consumer checks: one consumer per queue, messaging decorators outside of consumers. */\nexport function validateMessaging(ctx: ValidateContext<MessagingData>): void {\n const consumers = ctx.stored\n .filter((data): data is ConsumerData => data.kind === 'consumer')\n .sort((a, b) => compareStrings(a.token, b.token))\n\n // a queue is consumed by a single @Consumer class (the plugin refuses to boot otherwise)\n const byQueue = new Map<string, ConsumerData>()\n for (const consumer of consumers) {\n if (consumer.queue === '') continue\n const first = byQueue.get(consumer.queue)\n if (first === undefined) {\n byQueue.set(consumer.queue, consumer)\n continue\n }\n ctx.report({\n code: INVALID_CONSUMER,\n severity: 'error',\n message: `${first.displayName} and ${consumer.displayName} both consume \"${consumer.queue}\"`,\n location: consumer.location,\n hints: [\n 'A queue is consumed by a single @Consumer class: merge the handlers, or route by type with @OnMessage(type)',\n ],\n related: [{ message: `${first.displayName} consumes \"${consumer.queue}\"`, location: first.location }],\n })\n }\n\n // @OnMessage / @OnError / @Retry on a class that is neither a consumer nor one of its base classes\n const bases = new Set(consumers.flatMap(consumer => consumer.chain))\n for (const data of ctx.stored) {\n if (data.kind !== 'members' || data.abstract || bases.has(data.identity)) continue\n reportNotAConsumer(data, ctx)\n }\n}\n\nfunction reportNotAConsumer(data: MemberClassData, ctx: ValidateContext<MessagingData>): void {\n for (const decorator of data.decorators) {\n ctx.report({\n code: INVALID_DECORATOR,\n severity: 'error',\n message: `@${decorator.name} has no effect: ${data.displayName} is not a @Consumer`,\n location: decorator.location,\n hints: [\n `Add @Consumer('queue') to ${data.displayName}, or extend it from a @Consumer class`,\n 'Base classes holding shared handlers should be abstract',\n ],\n })\n }\n}\n","/**\n * `@znight/messaging/compiler`: the compiler extension of `@znight/messaging` (spec §5, §6.5, §9.2).\n *\n * Loaded by `@znight/compiler` through the package manifest (`package.json#znight.compiler`). It reads\n * `@Consumer` classes and their `@OnMessage` / `@Retry` / `@OnError` methods and `@Message` /\n * `@Headers` / `@Ctx` parameters, registers consumers as providers, reports invalid consumers at build\n * time and generates `metadata.extensions.messaging`.\n *\n * This entry only `import type`s from `@znight/compiler` and never loads the messaging runtime.\n */\nimport type { CompilerExtension, DecoratorSpec } from '@znight/compiler'\nimport type { MessagingData } from './data.ts'\n\nimport { analyzeMessagingClass } from './analyze.ts'\nimport { EXTENSION_NAME, MessagingDecorator } from './constants.ts'\nimport { generateMessaging } from './generate.ts'\nimport { validateMessaging } from './validate.ts'\n\nexport type {\n ConsumerData,\n HandlerData,\n HandlerParamData,\n MemberClassData,\n MessagingData,\n RetryPolicyData,\n} from './data.ts'\n\n/**\n * Decorators owned by the extension. `static` arguments must be statically evaluable (queue names,\n * types, retry options, header names); the `@Message` schema is a `value` (an exported binding).\n */\nconst decorators: Readonly<Record<string, DecoratorSpec>> = Object.freeze({\n [MessagingDecorator.Consumer]: { targets: ['class'], params: ['static'] },\n [MessagingDecorator.OnMessage]: { targets: ['method'], params: ['static'] },\n [MessagingDecorator.Retry]: { targets: ['method'], params: ['static'] },\n [MessagingDecorator.OnError]: { targets: ['method'], params: [] },\n [MessagingDecorator.Message]: { targets: ['parameter'], params: ['value'] },\n [MessagingDecorator.Headers]: { targets: ['parameter'], params: ['static'] },\n [MessagingDecorator.Ctx]: { targets: ['parameter'], params: [] },\n} satisfies Record<string, DecoratorSpec>)\n\n/** The `@znight/messaging` compiler extension. */\nexport const messagingCompilerExtension: CompilerExtension<MessagingData> = Object.freeze({\n apiVersion: 1,\n name: EXTENSION_NAME,\n decorators,\n analyzeClass: analyzeMessagingClass,\n validate: validateMessaging,\n generate: generateMessaging,\n})\n\nexport default messagingCompilerExtension\n"],"mappings":"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"}
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import { CoreLogger } from "@znight/core";
|
|
2
|
+
/**
|
|
3
|
+
* A message being handled by a consumer. It is the value of the request-scoped external
|
|
4
|
+
* `@znight/messaging#InboundMessage` during a delivery (inject it into request-scoped providers, or
|
|
5
|
+
* receive it with `@Ctx()`).
|
|
6
|
+
*
|
|
7
|
+
* Delivery is **at-least-once**: the same message may be handled more than once (redelivery after a
|
|
8
|
+
* crash, a lost ack, a retry...). Handlers must be idempotent; {@link id} is stable across
|
|
9
|
+
* redeliveries when the producer set it (Znight producers always do).
|
|
10
|
+
*/
|
|
11
|
+
interface InboundMessage<T = unknown> {
|
|
12
|
+
/** Message id: set by the producer (`MessageBroker.publish` generates a UUID), stable across redeliveries. */
|
|
13
|
+
readonly id: string;
|
|
14
|
+
/** Queue (RabbitMQ, SQS) or topic (Kafka) the consumer subscribed to. */
|
|
15
|
+
readonly queue: string;
|
|
16
|
+
/** Message type used to select the `@OnMessage(type)` handler, `undefined` when the producer set none. */
|
|
17
|
+
readonly type: string | undefined;
|
|
18
|
+
/** Decoded payload (the schema output when the handler declares `@Message(schema)`). */
|
|
19
|
+
readonly payload: T;
|
|
20
|
+
/** Message headers. Names are case-sensitive; non-string values are converted to strings. */
|
|
21
|
+
readonly headers: Readonly<Record<string, string>>;
|
|
22
|
+
/** Partition / ordering key (Kafka record key, SQS FIFO message group), when any. */
|
|
23
|
+
readonly key: string | undefined;
|
|
24
|
+
/** 1-based delivery attempt (broker delivery count or `x-znight-attempt` header). */
|
|
25
|
+
readonly attempt: number;
|
|
26
|
+
/** Attempts allowed by the retry policy of the selected handler (`1` without retries). */
|
|
27
|
+
readonly maxAttempts: number;
|
|
28
|
+
/** Whether the broker flagged the delivery as a redelivery. */
|
|
29
|
+
readonly redelivered: boolean;
|
|
30
|
+
/** When the message was produced (epoch milliseconds), when the broker reports it. */
|
|
31
|
+
readonly timestamp: number | undefined;
|
|
32
|
+
/** When this delivery was received (epoch milliseconds). */
|
|
33
|
+
readonly receivedAt: number;
|
|
34
|
+
/** Content type of the body. */
|
|
35
|
+
readonly contentType: string | undefined;
|
|
36
|
+
/** Encoded body, as received. */
|
|
37
|
+
readonly body: Uint8Array | string;
|
|
38
|
+
/** Name of the driver that received the message (`rabbitmq`, `sqs`, `kafka`, `memory`). */
|
|
39
|
+
readonly driver: string;
|
|
40
|
+
/** Driver-native message (amqplib `ConsumeMessage`, SQS `Message`, Kafka `Message`...). */
|
|
41
|
+
readonly raw: unknown;
|
|
42
|
+
/** Aborted when the consumer stops: long-running handlers can use it to stop early. */
|
|
43
|
+
readonly signal: AbortSignal;
|
|
44
|
+
}
|
|
45
|
+
/** Options of `MessageBroker.publish()`. */
|
|
46
|
+
interface PublishOptions {
|
|
47
|
+
/** Message type, used by consumers to select the `@OnMessage(type)` handler. */
|
|
48
|
+
readonly type?: string;
|
|
49
|
+
/** Additional headers (string values). */
|
|
50
|
+
readonly headers?: Readonly<Record<string, string>>;
|
|
51
|
+
/** Partition key (Kafka) or message group id (SQS FIFO queues). */
|
|
52
|
+
readonly key?: string;
|
|
53
|
+
/** Delays the delivery by this many milliseconds (support and maximum depend on the driver). */
|
|
54
|
+
readonly delay?: number;
|
|
55
|
+
/** Message id. Default: a random UUID. Set it to make publishing idempotent end-to-end. */
|
|
56
|
+
readonly id?: string;
|
|
57
|
+
/** Content type, when the payload is already encoded (`Uint8Array` or `string`). */
|
|
58
|
+
readonly contentType?: string;
|
|
59
|
+
}
|
|
60
|
+
/** Result of `MessageBroker.publish()`. */
|
|
61
|
+
interface PublishResult {
|
|
62
|
+
/** Id of the published message. */
|
|
63
|
+
readonly id: string;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* A message handed to a driver for publication: the payload is already encoded by the codec. The
|
|
67
|
+
* driver resolves `publish()` only once the broker confirmed the message (publisher confirms, SQS
|
|
68
|
+
* response, Kafka acks).
|
|
69
|
+
*/
|
|
70
|
+
interface OutboundMessage {
|
|
71
|
+
readonly id: string;
|
|
72
|
+
readonly type: string | undefined;
|
|
73
|
+
readonly key: string | undefined;
|
|
74
|
+
readonly headers: Readonly<Record<string, string>>;
|
|
75
|
+
readonly body: Uint8Array | string;
|
|
76
|
+
readonly contentType: string;
|
|
77
|
+
/** Production time, epoch milliseconds. */
|
|
78
|
+
readonly timestamp: number;
|
|
79
|
+
/** Requested delivery delay in milliseconds (`0`: immediate). */
|
|
80
|
+
readonly delayMs: number;
|
|
81
|
+
}
|
|
82
|
+
/** Why a message was moved to the dead-letter queue (`x-znight-dead-letter-reason` header). */
|
|
83
|
+
type DeadLetterReason = "no-handler" | "decode" | "validation" | "non-retryable" | "max-attempts";
|
|
84
|
+
/**
|
|
85
|
+
* What a driver can do. `MessagingPlugin` validates every `@Retry` policy against it at boot: a
|
|
86
|
+
* delay is either waited in-process (`<= maxInProcessDelayMs`) or delegated to the broker
|
|
87
|
+
* (`nativeDelay`, `<= maxNativeDelayMs`); otherwise the application fails to start (ZNIGHT011).
|
|
88
|
+
*/
|
|
89
|
+
interface DriverCapabilities {
|
|
90
|
+
/** The broker can redeliver a message after a delay (SQS visibility, RabbitMQ TTL queue, Kafka retry topic). */
|
|
91
|
+
readonly nativeDelay: boolean;
|
|
92
|
+
/** Longest native redelivery delay, in milliseconds (`0` without native delay). */
|
|
93
|
+
readonly maxNativeDelayMs: number;
|
|
94
|
+
/**
|
|
95
|
+
* Longest delay the runtime may wait in-process while holding a delivery before asking the
|
|
96
|
+
* broker to redeliver it (the message stays locked: prefetch slot, SQS lease...).
|
|
97
|
+
*/
|
|
98
|
+
readonly maxInProcessDelayMs: number;
|
|
99
|
+
/**
|
|
100
|
+
* How attempts are counted: `native` (broker delivery count: SQS `ApproximateReceiveCount`,
|
|
101
|
+
* RabbitMQ quorum `x-delivery-count`) or `header` (`x-znight-attempt` on republished retries).
|
|
102
|
+
*/
|
|
103
|
+
readonly deliveryCount: "native" | "header";
|
|
104
|
+
/** Longest `publish(..., { delay })`, in milliseconds (`0`: delayed publishing unsupported). */
|
|
105
|
+
readonly maxPublishDelayMs: number;
|
|
106
|
+
}
|
|
107
|
+
/** Services a driver receives when it connects. */
|
|
108
|
+
interface DriverContext {
|
|
109
|
+
/** Logger for background failures (polling errors, connection loss...). */
|
|
110
|
+
readonly logger: CoreLogger;
|
|
111
|
+
}
|
|
112
|
+
/** Redelivery request of a failed delivery. */
|
|
113
|
+
interface RetryRequest {
|
|
114
|
+
/** Attempt number of the redelivery (failed attempt + 1). */
|
|
115
|
+
readonly attempt: number;
|
|
116
|
+
/** Delay before the redelivery, in milliseconds (`0`: as soon as possible). */
|
|
117
|
+
readonly delayMs: number;
|
|
118
|
+
/** Error of the failed attempt. */
|
|
119
|
+
readonly error: unknown;
|
|
120
|
+
}
|
|
121
|
+
/** Dead-letter request of a delivery. */
|
|
122
|
+
interface DeadLetterRequest {
|
|
123
|
+
/**
|
|
124
|
+
* Destination queue/topic, `undefined` when dead-lettering is disabled for the consumer: the driver
|
|
125
|
+
* then rejects the message natively (RabbitMQ `nack` without requeue, so a queue DLX applies) or
|
|
126
|
+
* discards it.
|
|
127
|
+
*/
|
|
128
|
+
readonly queue: string | undefined;
|
|
129
|
+
readonly reason: DeadLetterReason;
|
|
130
|
+
readonly error: unknown;
|
|
131
|
+
/** Attempts made. */
|
|
132
|
+
readonly attempt: number;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* A message received by a driver, with the operations settling it. The runtime calls exactly one
|
|
136
|
+
* settlement operation (`ack`, `retry`, `deadLetter` or `release`), possibly followed by `release`
|
|
137
|
+
* when the first one failed. Each operation resolves once the broker acknowledged it.
|
|
138
|
+
*/
|
|
139
|
+
interface DriverDelivery {
|
|
140
|
+
readonly id: string;
|
|
141
|
+
readonly body: Uint8Array | string;
|
|
142
|
+
readonly contentType: string | undefined;
|
|
143
|
+
/** Headers as strings (non-string values converted). */
|
|
144
|
+
readonly headers: Readonly<Record<string, string>>;
|
|
145
|
+
readonly type: string | undefined;
|
|
146
|
+
readonly key: string | undefined;
|
|
147
|
+
/** 1-based attempt of this delivery. */
|
|
148
|
+
readonly attempt: number;
|
|
149
|
+
readonly redelivered: boolean;
|
|
150
|
+
/** Production time (epoch ms), when known. */
|
|
151
|
+
readonly timestamp: number | undefined;
|
|
152
|
+
/** Driver-native message. */
|
|
153
|
+
readonly raw: unknown;
|
|
154
|
+
/** The message was handled: remove it from the queue / commit it. */
|
|
155
|
+
ack(): Promise<void>;
|
|
156
|
+
/**
|
|
157
|
+
* Redeliver the message as attempt `request.attempt` after `request.delayMs`. The redelivery must be
|
|
158
|
+
* durable (confirmed) before the original is acknowledged.
|
|
159
|
+
*/
|
|
160
|
+
retry(request: RetryRequest): Promise<void>;
|
|
161
|
+
/** Move the message to the dead-letter destination (publish with confirmation, then acknowledge). */
|
|
162
|
+
deadLetter(request: DeadLetterRequest): Promise<void>;
|
|
163
|
+
/**
|
|
164
|
+
* Give the message back to the broker for a later redelivery without settling it (shutdown,
|
|
165
|
+
* failed dead-lettering). Must never lose the message.
|
|
166
|
+
*/
|
|
167
|
+
release(): Promise<void>;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Handles one delivery. The returned promise settles once the delivery was settled: drivers use it
|
|
171
|
+
* for back-pressure (never more than `concurrency` pending promises per subscription).
|
|
172
|
+
*/
|
|
173
|
+
type DeliveryHandler = (delivery: DriverDelivery) => Promise<void>;
|
|
174
|
+
/** Options of {@link MessagingDriver.subscribe}. */
|
|
175
|
+
interface SubscribeOptions {
|
|
176
|
+
/** Display name of the consumer class (logs, errors). */
|
|
177
|
+
readonly consumer: string;
|
|
178
|
+
/** Maximum number of deliveries handled concurrently (prefetch, receive batch size...). */
|
|
179
|
+
readonly concurrency: number;
|
|
180
|
+
/** Dead-letter destination, `undefined` when disabled. Drivers verify it exists at subscribe time. */
|
|
181
|
+
readonly deadLetterQueue: string | undefined;
|
|
182
|
+
/** Largest number of attempts among the consumer's handlers (e.g. checked against SQS `maxReceiveCount`). */
|
|
183
|
+
readonly maxAttempts: number;
|
|
184
|
+
/** Native retry delays (ms) the runtime may request: lets drivers prepare delay queues. Sorted, unique. */
|
|
185
|
+
readonly retryDelays: readonly number[];
|
|
186
|
+
/** Driver-specific options of `@Consumer({ queue, ...options })`. */
|
|
187
|
+
readonly options: Readonly<Record<string, unknown>>;
|
|
188
|
+
}
|
|
189
|
+
/** An active subscription. */
|
|
190
|
+
interface Subscription {
|
|
191
|
+
/** Stops receiving new deliveries. Deliveries already handed to the runtime can still be settled. */
|
|
192
|
+
cancel(): Promise<void>;
|
|
193
|
+
/** Releases the subscription's resources, once in-flight deliveries settled. Idempotent. */
|
|
194
|
+
close(): Promise<void>;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* A broker integration. Drivers live in subpath exports (`@znight/messaging/rabbitmq`, `/sqs`,
|
|
198
|
+
* `/kafka`, `/memory`) so their client libraries stay optional peers.
|
|
199
|
+
*/
|
|
200
|
+
interface MessagingDriver {
|
|
201
|
+
/** Short name (`rabbitmq`, `sqs`, `kafka`, `memory`), exposed as `InboundMessage.driver`. */
|
|
202
|
+
readonly name: string;
|
|
203
|
+
readonly capabilities: DriverCapabilities;
|
|
204
|
+
/** Connects to the broker (called in `onBootstrap`). */
|
|
205
|
+
connect(context: DriverContext): Promise<void>;
|
|
206
|
+
/** Starts consuming `queue`. Verifies the destination and its dead-letter configuration. */
|
|
207
|
+
subscribe(queue: string, handler: DeliveryHandler, options: SubscribeOptions): Promise<Subscription>;
|
|
208
|
+
/** Publishes a message; resolves once the broker confirmed it. */
|
|
209
|
+
publish(queue: string, message: OutboundMessage): Promise<void>;
|
|
210
|
+
/** Closes every subscription and the connection. Idempotent. */
|
|
211
|
+
close(): Promise<void>;
|
|
212
|
+
/** Default dead-letter destination of `queue` (`orders.dlq`, `orders-dlq`...). */
|
|
213
|
+
deadLetterName(queue: string): string;
|
|
214
|
+
}
|
|
215
|
+
export { DriverDelivery as a, SubscribeOptions as c, InboundMessage as d, OutboundMessage as f, DriverContext as i, Subscription as l, PublishResult as m, DeliveryHandler as n, MessagingDriver as o, PublishOptions as p, DriverCapabilities as r, RetryRequest as s, DeadLetterRequest as t, DeadLetterReason as u };
|
|
216
|
+
//# sourceMappingURL=driver-ZxLqy_Ap.d.mts.map
|