slackmark 0.4.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +44 -27
- package/dist/adapters/code-fence-adapter.d.ts +1 -1
- package/dist/adapters/code-fence-adapter.d.ts.map +1 -1
- package/dist/adapters/inline.d.ts.map +1 -1
- package/dist/adapters/math-block-adapter.d.ts +1 -1
- package/dist/adapters/math-block-adapter.d.ts.map +1 -1
- package/dist/adapters/mermaid-fence-adapter.d.ts.map +1 -1
- package/dist/adapters/try-render-image.d.ts +9 -0
- package/dist/adapters/try-render-image.d.ts.map +1 -0
- package/dist/assemble/message-assembler.d.ts +10 -0
- package/dist/assemble/message-assembler.d.ts.map +1 -1
- package/dist/budget/conversion-context.d.ts +5 -1
- package/dist/budget/conversion-context.d.ts.map +1 -1
- package/dist/budget/operation-scope.d.ts +9 -0
- package/dist/budget/operation-scope.d.ts.map +1 -0
- package/dist/budget/recording-receipt-collector.d.ts +13 -0
- package/dist/budget/recording-receipt-collector.d.ts.map +1 -0
- package/dist/capabilities/capabilities.d.ts +0 -1
- package/dist/capabilities/capabilities.d.ts.map +1 -1
- package/dist/constants.d.ts +6 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/converter/create-converter.d.ts +1 -1
- package/dist/converter/create-converter.d.ts.map +1 -1
- package/dist/converter/resolve-config.d.ts +4 -2
- package/dist/converter/resolve-config.d.ts.map +1 -1
- package/dist/converter/slackmark-converter.d.ts +11 -1
- package/dist/converter/slackmark-converter.d.ts.map +1 -1
- package/dist/errors.d.ts +81 -3
- package/dist/errors.d.ts.map +1 -1
- package/dist/index.d.ts +6 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4911 -3556
- package/dist/index.js.map +1 -1
- package/dist/receipts.d.ts +37 -0
- package/dist/receipts.d.ts.map +1 -0
- package/dist/renderers/codecogs-renderer.d.ts +5 -5
- package/dist/renderers/codecogs-renderer.d.ts.map +1 -1
- package/dist/renderers/kroki-renderer.d.ts +5 -5
- package/dist/renderers/kroki-renderer.d.ts.map +1 -1
- package/dist/renderers/mermaid-ink-renderer.d.ts +5 -5
- package/dist/renderers/mermaid-ink-renderer.d.ts.map +1 -1
- package/dist/renderers/quickchart-renderer.d.ts +5 -5
- package/dist/renderers/quickchart-renderer.d.ts.map +1 -1
- package/dist/renderers/renderer-options.d.ts +4 -0
- package/dist/renderers/renderer-options.d.ts.map +1 -0
- package/dist/renderers/url-utils.d.ts.map +1 -1
- package/dist/renderers.js +401 -248
- package/dist/renderers.js.map +1 -1
- package/dist/slack/fetch-slack-uploader.d.ts +11 -2
- package/dist/slack/fetch-slack-uploader.d.ts.map +1 -1
- package/dist/slack/slack-upload-error.d.ts +18 -2
- package/dist/slack/slack-upload-error.d.ts.map +1 -1
- package/dist/slack.d.ts +1 -1
- package/dist/slack.d.ts.map +1 -1
- package/dist/slack.js +743 -230
- package/dist/slack.js.map +1 -1
- package/dist/types.d.ts +93 -9
- package/dist/types.d.ts.map +1 -1
- package/dist/validate/validate-blocks.d.ts.map +1 -1
- package/package.json +5 -4
package/dist/slack.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/slack/slack-upload-error.ts","../src/slack/fetch-slack-uploader.ts"],"sourcesContent":["export const SlackUploadStage = {\n GetUploadUrl: \"get-upload-url\",\n UploadBytes: \"upload-bytes\",\n CompleteUpload: \"complete-upload\",\n FileInfo: \"file-info\",\n ProcessingTimeout: \"processing-timeout\",\n} as const;\n\nexport type SlackUploadStage = (typeof SlackUploadStage)[keyof typeof SlackUploadStage];\n\nexport interface SlackUploadErrorDetails {\n readonly stage: SlackUploadStage;\n readonly status?: number;\n readonly code?: string;\n readonly cause?: unknown;\n}\n\n/**\n * Integration error from one explicit stage of Slack's external-upload flow.\n */\nexport class SlackUploadError extends Error {\n override readonly name: string;\n readonly stage: SlackUploadStage;\n readonly status: number | undefined;\n readonly code: string | undefined;\n\n constructor(message: string, details: SlackUploadErrorDetails) {\n super(message, details.cause !== undefined ? { cause: details.cause } : undefined);\n this.name = \"SlackUploadError\";\n this.stage = details.stage;\n this.status = details.status;\n this.code = details.code;\n }\n}\n","import type { BytesImage, SlackUploader } from \"../types.js\";\n\nimport {\n SlackUploadError,\n SlackUploadStage,\n type SlackUploadStage as SlackUploadStageType,\n} from \"./slack-upload-error.js\";\n\nconst SLACK_API_BASE_URL = \"https://slack.com/api\";\nconst DEFAULT_POLL_INTERVAL_MS = 250;\nconst DEFAULT_POLL_MAX_ATTEMPTS = 20;\nconst DEFAULT_POLL_TIMEOUT_MS = 30_000;\n\nexport interface SlackFetchRequestInit {\n readonly method: \"POST\";\n readonly headers: Readonly<Record<string, string>>;\n readonly body: string | Uint8Array;\n}\n\nexport interface SlackFetchResponse {\n readonly ok: boolean;\n readonly status: number;\n json(): Promise<unknown>;\n}\n\nexport type SlackFetch = (\n input: string,\n init: SlackFetchRequestInit,\n) => Promise<SlackFetchResponse>;\n\nexport type SlackUploadSleep = (milliseconds: number) => Promise<void>;\nexport type SlackUploadClock = () => number;\n\nexport interface SlackUploadPollOptions {\n readonly intervalMs?: number;\n readonly maxAttempts?: number;\n readonly timeoutMs?: number;\n readonly sleep?: SlackUploadSleep;\n readonly clock?: SlackUploadClock;\n}\n\nexport interface FetchSlackUploaderOptions {\n readonly token: string;\n readonly fetch?: SlackFetch;\n readonly channelId?: string;\n readonly poll?: SlackUploadPollOptions;\n}\n\ninterface UploadTarget {\n readonly uploadUrl: string;\n readonly fileId: string;\n}\n\n/**\n * Web-standard implementation of Slack's external file-upload flow.\n *\n * @see https://docs.slack.dev/messaging/working-with-files\n */\nexport class FetchSlackUploader implements SlackUploader {\n private readonly token: string;\n private readonly fetcher: SlackFetch;\n private readonly channelId: string | undefined;\n private readonly pollIntervalMs: number;\n private readonly pollMaxAttempts: number;\n private readonly pollTimeoutMs: number;\n private readonly sleep: SlackUploadSleep;\n private readonly clock: SlackUploadClock;\n\n constructor(options: FetchSlackUploaderOptions) {\n this.token = options.token;\n this.fetcher = options.fetch ?? defaultFetch;\n this.channelId = options.channelId;\n this.pollIntervalMs = options.poll?.intervalMs ?? DEFAULT_POLL_INTERVAL_MS;\n this.pollMaxAttempts = options.poll?.maxAttempts ?? DEFAULT_POLL_MAX_ATTEMPTS;\n this.pollTimeoutMs = options.poll?.timeoutMs ?? DEFAULT_POLL_TIMEOUT_MS;\n this.sleep = options.poll?.sleep ?? defaultSleep;\n this.clock = options.poll?.clock ?? defaultClock;\n\n validateOptions({\n token: this.token,\n pollIntervalMs: this.pollIntervalMs,\n pollMaxAttempts: this.pollMaxAttempts,\n pollTimeoutMs: this.pollTimeoutMs,\n });\n }\n\n async upload(img: BytesImage): Promise<{ readonly fileId: string }> {\n const target = await this.getUploadTarget(img);\n await this.uploadBytes(target, img);\n await this.completeUpload(target.fileId, img.filename);\n await this.waitUntilProcessed(target.fileId);\n return { fileId: target.fileId };\n }\n\n private async getUploadTarget(img: BytesImage): Promise<UploadTarget> {\n const payload = await this.callSlackApi(\n \"files.getUploadURLExternal\",\n encodeForm([\n [\"filename\", img.filename],\n [\"length\", String(img.data.byteLength)],\n ]),\n SlackUploadStage.GetUploadUrl,\n );\n const uploadUrl = payload[\"upload_url\"];\n const fileId = payload[\"file_id\"];\n if (!isNonEmptyString(uploadUrl) || !isNonEmptyString(fileId)) {\n throw new SlackUploadError(\"files.getUploadURLExternal returned no upload_url or file_id\", {\n stage: SlackUploadStage.GetUploadUrl,\n code: \"invalid_response\",\n });\n }\n return { uploadUrl, fileId };\n }\n\n private async uploadBytes(target: UploadTarget, img: BytesImage): Promise<void> {\n let response: SlackFetchResponse;\n try {\n response = await this.fetcher(target.uploadUrl, {\n method: \"POST\",\n headers: { \"content-type\": img.mimeType },\n body: img.data,\n });\n } catch (cause) {\n throw new SlackUploadError(\"Uploading bytes to Slack failed\", {\n stage: SlackUploadStage.UploadBytes,\n code: \"fetch_failed\",\n cause,\n });\n }\n if (!response.ok) {\n throw new SlackUploadError(`Slack upload URL returned HTTP ${String(response.status)}`, {\n stage: SlackUploadStage.UploadBytes,\n status: response.status,\n code: `http_${String(response.status)}`,\n });\n }\n }\n\n private async completeUpload(fileId: string, filename: string): Promise<void> {\n const fields: Array<readonly [string, string]> = [\n [\n \"files\",\n JSON.stringify([\n {\n id: fileId,\n title: filename,\n },\n ]),\n ],\n ];\n if (this.channelId !== undefined) {\n fields.push([\"channel_id\", this.channelId]);\n }\n await this.callSlackApi(\n \"files.completeUploadExternal\",\n encodeForm(fields),\n SlackUploadStage.CompleteUpload,\n );\n }\n\n private async waitUntilProcessed(fileId: string): Promise<void> {\n const startedAt = this.clock();\n\n for (let attempt = 1; attempt <= this.pollMaxAttempts; attempt += 1) {\n const payload = await this.callSlackApi(\n \"files.info\",\n encodeForm([[\"file\", fileId]]),\n SlackUploadStage.FileInfo,\n );\n if (isProcessedImageFile(payload[\"file\"])) {\n return;\n }\n\n if (attempt === this.pollMaxAttempts || this.clock() - startedAt >= this.pollTimeoutMs) {\n throw processingTimeout(fileId, attempt);\n }\n\n try {\n await this.sleep(this.pollIntervalMs);\n } catch (cause) {\n throw new SlackUploadError(\"Slack file-processing poll sleep failed\", {\n stage: SlackUploadStage.ProcessingTimeout,\n code: \"sleep_failed\",\n cause,\n });\n }\n\n if (this.clock() - startedAt >= this.pollTimeoutMs) {\n throw processingTimeout(fileId, attempt);\n }\n }\n }\n\n private async callSlackApi(\n method: string,\n body: string,\n stage: SlackUploadStageType,\n ): Promise<Record<string, unknown>> {\n let response: SlackFetchResponse;\n try {\n response = await this.fetcher(`${SLACK_API_BASE_URL}/${method}`, {\n method: \"POST\",\n headers: {\n authorization: `Bearer ${this.token}`,\n \"content-type\": \"application/x-www-form-urlencoded;charset=UTF-8\",\n },\n body,\n });\n } catch (cause) {\n throw new SlackUploadError(`${method} request failed`, {\n stage,\n code: \"fetch_failed\",\n cause,\n });\n }\n\n let payload: unknown;\n try {\n payload = await response.json();\n } catch (cause) {\n throw new SlackUploadError(`${method} returned invalid JSON`, {\n stage,\n status: response.status,\n code: \"invalid_json\",\n cause,\n });\n }\n\n const slackCode = getSlackErrorCode(payload);\n if (!response.ok || !isRecord(payload) || payload[\"ok\"] !== true) {\n throw new SlackUploadError(`${method} was rejected by Slack`, {\n stage,\n status: response.status,\n code: slackCode ?? (response.ok ? \"invalid_response\" : `http_${String(response.status)}`),\n });\n }\n return payload;\n }\n}\n\nfunction validateOptions(uploader: {\n readonly token: string;\n readonly pollIntervalMs: number;\n readonly pollMaxAttempts: number;\n readonly pollTimeoutMs: number;\n}): void {\n if (uploader.token.length === 0) {\n throw new TypeError(\"token must not be empty\");\n }\n if (!Number.isInteger(uploader.pollIntervalMs) || uploader.pollIntervalMs < 0) {\n throw new RangeError(\"poll.intervalMs must be a non-negative integer\");\n }\n if (!Number.isInteger(uploader.pollMaxAttempts) || uploader.pollMaxAttempts <= 0) {\n throw new RangeError(\"poll.maxAttempts must be a positive integer\");\n }\n if (!Number.isFinite(uploader.pollTimeoutMs) || uploader.pollTimeoutMs <= 0) {\n throw new RangeError(\"poll.timeoutMs must be positive\");\n }\n}\n\nfunction encodeForm(fields: ReadonlyArray<readonly [string, string]>): string {\n return fields\n .map(([name, value]) => `${encodeURIComponent(name)}=${encodeURIComponent(value)}`)\n .join(\"&\");\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction isNonEmptyString(value: unknown): value is string {\n return typeof value === \"string\" && value.length > 0;\n}\n\nfunction isPositiveNumber(value: unknown): value is number {\n return typeof value === \"number\" && Number.isFinite(value) && value > 0;\n}\n\nfunction isProcessedImageFile(value: unknown): boolean {\n if (!isRecord(value)) {\n return false;\n }\n return (\n isNonEmptyString(value[\"mimetype\"]) &&\n isNonEmptyString(value[\"filetype\"]) &&\n isPositiveNumber(value[\"original_w\"]) &&\n isPositiveNumber(value[\"original_h\"])\n );\n}\n\nfunction getSlackErrorCode(payload: unknown): string | undefined {\n if (!isRecord(payload)) {\n return undefined;\n }\n const error = payload[\"error\"];\n return typeof error === \"string\" ? error : undefined;\n}\n\nfunction processingTimeout(fileId: string, attempts: number): SlackUploadError {\n return new SlackUploadError(\n `Slack file ${fileId} was not processed after ${String(attempts)} polls`,\n {\n stage: SlackUploadStage.ProcessingTimeout,\n code: \"processing_timeout\",\n },\n );\n}\n\nfunction defaultFetch(input: string, init: SlackFetchRequestInit): Promise<SlackFetchResponse> {\n return globalThis.fetch(input, init);\n}\n\nfunction defaultSleep(milliseconds: number): Promise<void> {\n return new Promise((resolve) => {\n setTimeout(resolve, milliseconds);\n });\n}\n\nfunction defaultClock(): number {\n return Date.now();\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"file":"slack.js","names":[],"sources":["../src/receipts.ts","../src/errors.ts","../src/slack/slack-upload-error.ts","../src/slack/fetch-slack-uploader.ts"],"sourcesContent":["export const UploadPhase = {\n Requested: \"requested\",\n Allocated: \"allocated\",\n Uploaded: \"uploaded\",\n Completed: \"completed\",\n Shared: \"shared\",\n Unknown: \"unknown\",\n} as const;\n\nexport type UploadPhase = (typeof UploadPhase)[keyof typeof UploadPhase];\n\nexport const UploadProcessing = {\n NotRequested: \"not-requested\",\n Pending: \"pending\",\n Verified: \"verified\",\n Unverified: \"unverified\",\n} as const;\n\nexport type UploadProcessing = (typeof UploadProcessing)[keyof typeof UploadProcessing];\n\nexport const RetrySafety = {\n Never: \"never\",\n Safe: \"safe\",\n MayDuplicate: \"may-duplicate\",\n} as const;\n\nexport type RetrySafety = (typeof RetrySafety)[keyof typeof RetrySafety];\n\nexport interface UploadReceipt {\n readonly kind: \"upload\";\n readonly provider: string;\n readonly rendererId?: string | undefined;\n readonly filename?: string | undefined;\n readonly phase: UploadPhase;\n readonly fileId?: string | undefined;\n readonly shared: boolean;\n readonly processing: UploadProcessing;\n readonly status?: number | undefined;\n readonly retryAfterMs?: number | undefined;\n readonly providerCode?: string | undefined;\n readonly retrySafety: RetrySafety;\n}\n","import type { UploadReceipt } from \"./receipts.js\";\n\n/**\n * Registry-keyed markers, not module-local symbols.\n *\n * Each published entry (`slackmark`, `slackmark/renderers`, `slackmark/slack`) is bundled\n * without code splitting, so every entry carries its own copy of these classes and\n * `instanceof` is false for an error that crosses an entry boundary. `Symbol.for` keys are\n * shared by every copy, which is what makes the exported guards below reliable. Prefer\n * those guards to `instanceof` for any error that can cross an entry.\n */\nconst RECEIPT_SNAPSHOT_LOCK = Symbol.for(\"slackmark.receiptSnapshotLock\");\nconst OPERATION_ERROR_CARRIER = Symbol.for(\"slackmark.operationErrorCarrier\");\nconst CONFIGURATION_ERROR_BRAND = Symbol.for(\"slackmark.error.configuration\");\nconst OPERATION_ERROR_BRAND = Symbol.for(\"slackmark.error.operation\");\n\n/**\n * Marks a class prototype so instances from any bundled copy answer to one identity.\n * Subclasses inherit the brand, and instances carry no extra own property.\n */\nexport function brandErrorPrototype(prototype: object, brand: symbol): void {\n Object.defineProperty(prototype, brand, {\n configurable: false,\n enumerable: false,\n value: true,\n writable: false,\n });\n}\n\n/**\n * Reads a brand without trusting the value: a hostile getter must not escape a guard.\n */\nexport function hasErrorBrand(value: unknown, brand: symbol): boolean {\n if (typeof value !== \"object\" || value === null) {\n return false;\n }\n try {\n return Reflect.get(value, brand) === true;\n } catch {\n return false;\n }\n}\n\n/**\n * Programmer/configuration error thrown only from the composition root.\n */\nexport interface ConfigurationErrorOptions {\n readonly code?: string | undefined;\n readonly stage?: string | undefined;\n readonly receipts?: ReadonlyArray<UploadReceipt> | undefined;\n readonly settledReceipts?: Promise<ReadonlyArray<UploadReceipt>> | undefined;\n readonly cause?: unknown;\n}\n\nexport class ConfigurationError extends Error {\n static {\n brandErrorPrototype(this.prototype, CONFIGURATION_ERROR_BRAND);\n }\n\n override readonly name: string;\n readonly code: string;\n readonly stage: string | undefined;\n readonly retryable: false;\n readonly receipts: ReadonlyArray<UploadReceipt>;\n readonly settledReceipts: Promise<ReadonlyArray<UploadReceipt>>;\n\n constructor(message: string, options: ConfigurationErrorOptions = {}) {\n super(message, options?.cause !== undefined ? { cause: options.cause } : undefined);\n this.name = \"ConfigurationError\";\n this.code = options.code ?? \"invalid_configuration\";\n this.stage = options.stage;\n this.retryable = false;\n this.receipts = freezeReceipts(options.receipts ?? []);\n this.settledReceipts = options.settledReceipts ?? Promise.resolve(this.receipts);\n }\n}\n\nexport const OperationErrorCode = {\n Aborted: \"operation_aborted\",\n DeadlineExceeded: \"operation_deadline_exceeded\",\n Shutdown: \"operation_shutdown\",\n} as const;\n\nexport type OperationErrorCode = (typeof OperationErrorCode)[keyof typeof OperationErrorCode];\n\nexport interface OperationErrorOptions {\n readonly receipts?: ReadonlyArray<UploadReceipt> | undefined;\n readonly settledReceipts?: Promise<ReadonlyArray<UploadReceipt>> | undefined;\n readonly cause?: unknown;\n}\n\n/**\n * Operational control-flow error. These failures are never degradations.\n */\nexport class OperationError extends Error {\n static {\n brandErrorPrototype(this.prototype, OPERATION_ERROR_BRAND);\n }\n\n override readonly name: string;\n readonly code: OperationErrorCode;\n readonly stage: string;\n readonly retryable: boolean;\n readonly receipts: ReadonlyArray<UploadReceipt>;\n readonly settledReceipts: Promise<ReadonlyArray<UploadReceipt>>;\n\n constructor(\n message: string,\n code: OperationErrorCode,\n stage: string,\n retryable: boolean,\n options: OperationErrorOptions = {},\n ) {\n super(message, options.cause !== undefined ? { cause: options.cause } : undefined);\n this.name = \"OperationError\";\n this.code = code;\n this.stage = stage;\n this.retryable = retryable;\n this.receipts = freezeReceipts(options.receipts ?? []);\n this.settledReceipts = options.settledReceipts ?? Promise.resolve(this.receipts);\n }\n}\n\nexport class OperationAbortedError extends OperationError {\n override readonly name: string;\n\n constructor(stage: string, options: OperationErrorOptions = {}) {\n super(\"Operation aborted by caller\", OperationErrorCode.Aborted, stage, false, options);\n this.name = \"OperationAbortedError\";\n }\n}\n\nexport class OperationDeadlineExceededError extends OperationError {\n override readonly name: string;\n\n constructor(stage: string, options: OperationErrorOptions = {}) {\n super(\"Operation deadline exceeded\", OperationErrorCode.DeadlineExceeded, stage, true, options);\n this.name = \"OperationDeadlineExceededError\";\n }\n}\n\nexport class OperationShutdownError extends OperationError {\n override readonly name: string;\n\n constructor(stage: string, options: OperationErrorOptions = {}) {\n super(\"Operation interrupted by shutdown\", OperationErrorCode.Shutdown, stage, true, options);\n this.name = \"OperationShutdownError\";\n }\n}\n\n/**\n * Identifies a {@link ConfigurationError} from any entry of this package.\n *\n * Use this instead of `instanceof` when the error may have been thrown by a different\n * entry — for example a `ConfigurationError` from `slackmark/renderers` caught by code\n * that imported the class from `slackmark`.\n */\nexport function isConfigurationError(value: unknown): value is ConfigurationError {\n return hasErrorBrand(value, CONFIGURATION_ERROR_BRAND);\n}\n\n/**\n * Identifies an {@link OperationError} — abort, deadline, or shutdown — from any entry of\n * this package, including its subclasses.\n *\n * Use this instead of `instanceof` when the error may have been thrown by a different\n * entry — for example an abort raised inside `FetchSlackUploader` from `slackmark/slack`\n * caught by code that imported the class from `slackmark`. Narrow further with `code`\n * against {@link OperationErrorCode} rather than testing a subclass with `instanceof`.\n */\nexport function isOperationError(value: unknown): value is OperationError {\n return hasErrorBrand(value, OPERATION_ERROR_BRAND);\n}\n\nexport function cloneOperationError(error: OperationError, fallbackStage: string): OperationError {\n const stage = error.stage.length > 0 ? error.stage : fallbackStage;\n const options: OperationErrorOptions = {\n cause: error,\n receipts: error.receipts,\n settledReceipts: error.settledReceipts,\n };\n let cloned: OperationError;\n switch (error.code) {\n case OperationErrorCode.Aborted:\n cloned = new OperationAbortedError(stage, options);\n break;\n case OperationErrorCode.DeadlineExceeded:\n cloned = new OperationDeadlineExceededError(stage, options);\n break;\n case OperationErrorCode.Shutdown:\n cloned = new OperationShutdownError(stage, options);\n break;\n }\n Reflect.defineProperty(cloned, OPERATION_ERROR_CARRIER, {\n configurable: false,\n enumerable: false,\n value: true,\n writable: false,\n });\n return cloned;\n}\n\nexport function isOperationErrorCarrier(error: OperationError): boolean {\n return Reflect.get(error, OPERATION_ERROR_CARRIER) === true;\n}\n\nexport function cloneConfigurationError(error: ConfigurationError): ConfigurationError {\n return new ConfigurationError(error.message, {\n code: error.code,\n stage: error.stage,\n cause: error,\n receipts: error.receipts,\n settledReceipts: error.settledReceipts,\n });\n}\n\nexport function attachReceipts(\n error: unknown,\n receipts: ReadonlyArray<UploadReceipt>,\n settledReceipts?: Promise<ReadonlyArray<UploadReceipt>>,\n): unknown {\n if (!(error instanceof Error)) {\n return error;\n }\n try {\n if (Reflect.get(error, RECEIPT_SNAPSHOT_LOCK) === true) {\n return error;\n }\n } catch {\n return error;\n }\n let existing: ReadonlyArray<UploadReceipt> = [];\n try {\n const candidate = Reflect.get(error, \"receipts\");\n if (Array.isArray(candidate)) {\n existing = candidate.filter(isUploadReceipt);\n }\n } catch {\n existing = [];\n }\n Reflect.defineProperty(error, \"receipts\", {\n configurable: true,\n enumerable: true,\n value: freezeReceipts(mergeReceipts(existing, receipts)),\n writable: false,\n });\n if (settledReceipts !== undefined) {\n const finalReceipts = freezeSettledReceipts(settledReceipts, receipts);\n Reflect.defineProperty(error, \"settledReceipts\", {\n configurable: true,\n enumerable: true,\n value: finalReceipts,\n writable: false,\n });\n }\n return error;\n}\n\nexport function lockReceiptSnapshot(error: unknown): unknown {\n if (error instanceof Error) {\n Reflect.defineProperty(error, RECEIPT_SNAPSHOT_LOCK, {\n configurable: false,\n enumerable: false,\n value: true,\n writable: false,\n });\n }\n return error;\n}\n\nasync function freezeSettledReceipts(\n settledReceipts: Promise<ReadonlyArray<UploadReceipt>>,\n fallback: ReadonlyArray<UploadReceipt>,\n): Promise<ReadonlyArray<UploadReceipt>> {\n try {\n return freezeReceipts(await settledReceipts);\n } catch {\n return freezeReceipts(fallback);\n }\n}\n\nfunction mergeReceipts(\n existing: ReadonlyArray<UploadReceipt>,\n incoming: ReadonlyArray<UploadReceipt>,\n): ReadonlyArray<UploadReceipt> {\n const existingGroups = groupReceipts(existing);\n const incomingGroups = groupReceipts(incoming);\n const merged: UploadReceipt[] = [...incoming];\n for (const [key, values] of existingGroups) {\n const overlap = incomingGroups.get(key)?.length ?? 0;\n if (values.length > overlap) {\n merged.push(...values.slice(overlap));\n }\n }\n return merged;\n}\n\nfunction groupReceipts(\n receipts: ReadonlyArray<UploadReceipt>,\n): ReadonlyMap<string, ReadonlyArray<UploadReceipt>> {\n const grouped = new Map<string, UploadReceipt[]>();\n for (const receipt of receipts) {\n const key = receiptKey(receipt);\n const values = grouped.get(key);\n if (values === undefined) {\n grouped.set(key, [receipt]);\n } else {\n values.push(receipt);\n }\n }\n return grouped;\n}\n\nfunction receiptKey(receipt: UploadReceipt): string {\n return [\n receipt.provider,\n receipt.phase,\n receipt.fileId ?? \"\",\n String(receipt.shared),\n receipt.processing,\n String(receipt.status ?? \"\"),\n String(receipt.retryAfterMs ?? \"\"),\n receipt.providerCode ?? \"\",\n receipt.retrySafety,\n ].join(\"\\u0000\");\n}\n\nfunction freezeReceipts(receipts: ReadonlyArray<UploadReceipt>): ReadonlyArray<UploadReceipt> {\n return Object.freeze(receipts.map((receipt) => Object.freeze({ ...receipt })));\n}\n\nfunction isUploadReceipt(value: unknown): value is UploadReceipt {\n return typeof value === \"object\" && value !== null && Reflect.get(value, \"kind\") === \"upload\";\n}\n","import { brandErrorPrototype, hasErrorBrand } from \"../errors.js\";\nimport { RetrySafety, UploadPhase, UploadProcessing, type UploadReceipt } from \"../types.js\";\n\n/** See the brand rationale in `errors.ts`: this class is bundled into more than one entry. */\nconst SLACK_UPLOAD_ERROR_BRAND = Symbol.for(\"slackmark.error.slackUpload\");\n\nexport const SlackUploadStage = {\n Admission: \"admission\",\n GetUploadUrl: \"get-upload-url\",\n UploadBytes: \"upload-bytes\",\n CompleteUpload: \"complete-upload\",\n FileInfo: \"file-info\",\n ProcessingTimeout: \"processing-timeout\",\n} as const;\n\nexport type SlackUploadStage = (typeof SlackUploadStage)[keyof typeof SlackUploadStage];\n\nexport interface SlackUploadErrorDetails {\n readonly stage: SlackUploadStage;\n readonly status?: number | undefined;\n readonly code?: string | undefined;\n readonly retryable?: boolean | undefined;\n readonly retryAfterMs?: number | undefined;\n readonly receipt?: UploadReceipt | undefined;\n readonly cause?: unknown;\n}\n\n/**\n * Integration error from one explicit stage of Slack's external-upload flow.\n */\nexport class SlackUploadError extends Error {\n static {\n brandErrorPrototype(this.prototype, SLACK_UPLOAD_ERROR_BRAND);\n }\n\n override readonly name: string;\n readonly stage: SlackUploadStage;\n readonly status: number | undefined;\n readonly code: string | undefined;\n readonly retryable: boolean;\n readonly retryAfterMs: number | undefined;\n readonly receipt: UploadReceipt;\n readonly receipts: ReadonlyArray<UploadReceipt>;\n readonly settledReceipts: Promise<ReadonlyArray<UploadReceipt>>;\n\n constructor(message: string, details: SlackUploadErrorDetails) {\n super(message, details.cause !== undefined ? { cause: details.cause } : undefined);\n this.name = \"SlackUploadError\";\n this.stage = details.stage;\n this.status = details.status;\n this.code = details.code;\n this.retryable = details.retryable ?? isRetryable(details.status, details.code);\n this.retryAfterMs = details.retryAfterMs;\n this.receipt = Object.freeze(\n details.receipt ?? {\n kind: \"upload\",\n provider: \"slack\",\n phase: UploadPhase.Requested,\n fileId: undefined,\n shared: false,\n processing: UploadProcessing.NotRequested,\n status: details.status,\n retryAfterMs: details.retryAfterMs,\n providerCode: details.code,\n retrySafety: RetrySafety.Safe,\n },\n );\n this.receipts = Object.freeze([this.receipt]);\n this.settledReceipts = Promise.resolve(this.receipts);\n }\n}\n\n/**\n * Identifies a {@link SlackUploadError} from any entry of this package. `slackmark` and\n * `slackmark/slack` each bundle their own copy, so `instanceof` is unreliable when the\n * error crosses between them.\n */\nexport function isSlackUploadError(value: unknown): value is SlackUploadError {\n return hasErrorBrand(value, SLACK_UPLOAD_ERROR_BRAND);\n}\n\nfunction isRetryable(status: number | undefined, code: string | undefined): boolean {\n return (\n status === 429 ||\n (status !== undefined && status >= 500) ||\n code === \"fetch_failed\" ||\n code === \"request_timeout\" ||\n code === \"processing_timeout\"\n );\n}\n","import {\n RetrySafety,\n UploadPhase,\n UploadProcessing,\n type BytesImage,\n type OperationContext,\n type SlackUploader,\n type UploadReceipt,\n} from \"../types.js\";\nimport {\n ConfigurationError,\n OperationAbortedError,\n OperationDeadlineExceededError,\n OperationErrorCode,\n attachReceipts,\n isOperationError,\n type OperationError,\n} from \"../errors.js\";\n\nimport {\n SlackUploadError,\n SlackUploadStage,\n isSlackUploadError,\n type SlackUploadStage as SlackUploadStageType,\n} from \"./slack-upload-error.js\";\n\nconst SLACK_API_BASE_URL = \"https://slack.com/api\";\nconst DEFAULT_POLL_INTERVAL_MS = 250;\nconst DEFAULT_POLL_MAX_ATTEMPTS = 20;\nconst DEFAULT_POLL_TIMEOUT_MS = 30_000;\nconst DEFAULT_REQUEST_TIMEOUT_MS = 10_000;\n\nexport interface SlackFetchRequestInit {\n readonly method: \"POST\";\n readonly headers: Readonly<Record<string, string>>;\n readonly body: string | Uint8Array;\n readonly signal?: AbortSignal;\n}\n\nexport interface SlackFetchResponse {\n readonly ok: boolean;\n readonly status: number;\n readonly headers?: { get(name: string): string | null };\n json(): Promise<unknown>;\n}\n\nexport type SlackFetch = (\n input: string,\n init: SlackFetchRequestInit,\n) => Promise<SlackFetchResponse>;\n\nexport type SlackUploadSleep = (milliseconds: number) => Promise<void>;\nexport type SlackUploadClock = () => number;\n\nexport interface SlackUploadPollOptions {\n readonly intervalMs?: number;\n readonly maxAttempts?: number;\n readonly timeoutMs?: number;\n readonly sleep?: SlackUploadSleep;\n readonly clock?: SlackUploadClock;\n}\n\nexport interface FetchSlackUploaderOptions {\n readonly token: string;\n readonly fetch?: SlackFetch;\n readonly channelId?: string;\n readonly requestTimeoutMs?: number;\n readonly waitForProcessing?: boolean;\n readonly poll?: SlackUploadPollOptions;\n}\n\ninterface UploadTarget {\n readonly uploadUrl: string;\n readonly fileId: string;\n}\n\ninterface ResolvedFetchSlackUploaderOptions {\n readonly token: string;\n readonly fetcher: SlackFetch;\n readonly channelId: string | undefined;\n readonly requestTimeoutMs: number;\n readonly waitForProcessing: boolean;\n readonly pollIntervalMs: number;\n readonly pollMaxAttempts: number;\n readonly pollTimeoutMs: number;\n readonly sleep: SlackUploadSleep;\n readonly clock: SlackUploadClock;\n}\n\n/**\n * Web-standard implementation of Slack's external file-upload flow.\n *\n * @see https://docs.slack.dev/messaging/working-with-files\n */\nexport class FetchSlackUploader implements SlackUploader {\n private readonly token: string;\n private readonly fetcher: SlackFetch;\n private readonly channelId: string | undefined;\n private readonly requestTimeoutMs: number;\n private readonly waitForProcessing: boolean;\n private readonly pollIntervalMs: number;\n private readonly pollMaxAttempts: number;\n private readonly pollTimeoutMs: number;\n private readonly sleep: SlackUploadSleep;\n private readonly clock: SlackUploadClock;\n\n constructor(options: FetchSlackUploaderOptions) {\n const resolved = resolveUploaderOptions(options);\n this.token = resolved.token;\n this.fetcher = resolved.fetcher;\n this.channelId = resolved.channelId;\n this.requestTimeoutMs = resolved.requestTimeoutMs;\n this.waitForProcessing = resolved.waitForProcessing;\n this.pollIntervalMs = resolved.pollIntervalMs;\n this.pollMaxAttempts = resolved.pollMaxAttempts;\n this.pollTimeoutMs = resolved.pollTimeoutMs;\n this.sleep = resolved.sleep;\n this.clock = resolved.clock;\n }\n\n async upload(\n img: BytesImage,\n context: OperationContext,\n ): Promise<{ readonly fileId: string; readonly receipt: UploadReceipt }> {\n let receipt = slackReceipt({\n phase: UploadPhase.Requested,\n processing: UploadProcessing.NotRequested,\n retrySafety: RetrySafety.Safe,\n });\n try {\n const target = await this.getUploadTarget(img, context);\n receipt = slackReceipt({\n phase: UploadPhase.Allocated,\n fileId: target.fileId,\n processing: UploadProcessing.NotRequested,\n retrySafety: RetrySafety.MayDuplicate,\n });\n await this.uploadBytes(target, img, context);\n receipt = slackReceipt({\n phase: UploadPhase.Uploaded,\n fileId: target.fileId,\n processing: UploadProcessing.NotRequested,\n retrySafety: RetrySafety.MayDuplicate,\n });\n await this.completeUpload(target.fileId, img.filename, context);\n receipt = slackReceipt({\n phase: this.channelId === undefined ? UploadPhase.Completed : UploadPhase.Shared,\n fileId: target.fileId,\n shared: this.channelId !== undefined,\n processing: this.waitForProcessing\n ? UploadProcessing.Pending\n : UploadProcessing.NotRequested,\n retrySafety: RetrySafety.Never,\n });\n if (this.waitForProcessing) {\n try {\n await this.waitUntilProcessed(target.fileId, receipt, context);\n receipt = slackReceipt({\n ...receipt,\n processing: UploadProcessing.Verified,\n });\n } catch (error) {\n if (isOperationError(error)) {\n throw attachReceipts(error, [receipt]);\n }\n if (isSlackUploadError(error)) {\n receipt = slackReceipt({\n ...receipt,\n processing: UploadProcessing.Unverified,\n status: error.status,\n retryAfterMs: error.retryAfterMs,\n providerCode: error.code,\n });\n } else {\n receipt = slackReceipt({\n ...receipt,\n processing: UploadProcessing.Unverified,\n providerCode: \"processing_failed\",\n });\n }\n }\n }\n return { fileId: target.fileId, receipt };\n } catch (error) {\n if (isSlackUploadError(error)) {\n throw withReceipt(error, receipt);\n }\n if (isOperationError(error)) {\n throw attachReceipts(error, [receipt]);\n }\n throw error;\n }\n }\n\n private async getUploadTarget(img: BytesImage, control: OperationContext): Promise<UploadTarget> {\n const payload = await this.callSlackApi(\n \"files.getUploadURLExternal\",\n encodeForm([\n [\"filename\", img.filename],\n [\"length\", String(img.data.byteLength)],\n ]),\n SlackUploadStage.GetUploadUrl,\n control,\n );\n const uploadUrl = payload[\"upload_url\"];\n const fileId = payload[\"file_id\"];\n if (!isNonEmptyString(uploadUrl) || !isNonEmptyString(fileId)) {\n throw new SlackUploadError(\"files.getUploadURLExternal returned no upload_url or file_id\", {\n stage: SlackUploadStage.GetUploadUrl,\n code: \"invalid_response\",\n });\n }\n return { uploadUrl, fileId };\n }\n\n private async uploadBytes(\n target: UploadTarget,\n img: BytesImage,\n control: OperationContext,\n ): Promise<void> {\n const stageSignal = createStageSignal(control, this.requestTimeoutMs, this.clock);\n let response: SlackFetchResponse;\n try {\n response = await this.fetcher(target.uploadUrl, {\n method: \"POST\",\n headers: { \"content-type\": img.mimeType },\n body: img.data,\n signal: stageSignal.signal,\n });\n } catch (cause) {\n const operationError = stageSignal.operationError(SlackUploadStage.UploadBytes, cause);\n if (operationError !== undefined) {\n throw operationError;\n }\n throw new SlackUploadError(\"Slack byte upload failed\", {\n stage: SlackUploadStage.UploadBytes,\n code: stageSignal.code(),\n cause,\n });\n } finally {\n stageSignal.cleanup();\n }\n if (!response.ok) {\n throw new SlackUploadError(\"Slack byte upload was rejected\", {\n stage: SlackUploadStage.UploadBytes,\n status: response.status,\n code: `http_${String(response.status)}`,\n retryAfterMs: retryAfterMs(response),\n });\n }\n }\n\n private async completeUpload(\n fileId: string,\n filename: string,\n control: OperationContext,\n ): Promise<void> {\n const fields: Array<readonly [string, string]> = [\n [\n \"files\",\n JSON.stringify([\n {\n id: fileId,\n title: filename,\n },\n ]),\n ],\n ];\n if (this.channelId !== undefined) {\n fields.push([\"channel_id\", this.channelId]);\n }\n await this.callSlackApi(\n \"files.completeUploadExternal\",\n encodeForm(fields),\n SlackUploadStage.CompleteUpload,\n control,\n );\n }\n\n private async waitUntilProcessed(\n fileId: string,\n receipt: UploadReceipt,\n control: OperationContext,\n ): Promise<void> {\n const startedAt = this.clock();\n const pollDeadlineMs = startedAt + this.pollTimeoutMs;\n const pollOwnsDeadline =\n control.deadlineMs === undefined || pollDeadlineMs < control.deadlineMs;\n const pollContext: OperationContext = {\n signal: control.signal,\n deadlineMs: Math.min(control.deadlineMs ?? Number.POSITIVE_INFINITY, pollDeadlineMs),\n };\n\n for (let attempt = 1; attempt <= this.pollMaxAttempts; attempt += 1) {\n if (this.clock() >= pollDeadlineMs) {\n throw processingTimeout(receipt, attempt - 1);\n }\n let payload: Record<string, unknown>;\n try {\n payload = await this.callSlackApi(\n \"files.info\",\n encodeForm([[\"file\", fileId]]),\n SlackUploadStage.FileInfo,\n pollContext,\n );\n } catch (error) {\n if (pollOwnsDeadline && isOperationDeadline(error)) {\n throw processingTimeout(receipt, attempt);\n }\n throw error;\n }\n if (isProcessedImageFile(payload[\"file\"])) {\n return;\n }\n\n if (attempt === this.pollMaxAttempts || this.clock() - startedAt >= this.pollTimeoutMs) {\n throw processingTimeout(receipt, attempt);\n }\n\n try {\n await controlledSleep(\n this.sleep,\n Math.min(this.pollIntervalMs, Math.max(0, pollDeadlineMs - this.clock())),\n pollContext,\n this.clock,\n );\n } catch (error) {\n if (pollOwnsDeadline && isOperationDeadline(error)) {\n throw processingTimeout(receipt, attempt);\n }\n throw error;\n }\n\n if (this.clock() - startedAt >= this.pollTimeoutMs) {\n throw processingTimeout(receipt, attempt);\n }\n }\n }\n\n private async callSlackApi(\n method: string,\n body: string,\n stage: SlackUploadStageType,\n control: OperationContext,\n ): Promise<Record<string, unknown>> {\n const stageSignal = createStageSignal(control, this.requestTimeoutMs, this.clock);\n let response: SlackFetchResponse;\n try {\n response = await this.fetcher(`${SLACK_API_BASE_URL}/${method}`, {\n method: \"POST\",\n headers: {\n authorization: `Bearer ${this.token}`,\n \"content-type\": \"application/x-www-form-urlencoded;charset=UTF-8\",\n },\n body,\n signal: stageSignal.signal,\n });\n } catch (cause) {\n const operationError = stageSignal.operationError(stage, cause);\n stageSignal.cleanup();\n if (operationError !== undefined) {\n throw operationError;\n }\n throw new SlackUploadError(\"Slack API request failed\", {\n stage,\n code: stageSignal.code(),\n cause,\n });\n }\n\n let payload: unknown;\n try {\n payload = await raceWithSignal(response.json(), stageSignal.signal);\n } catch (cause) {\n const operationError = stageSignal.operationError(stage, cause);\n const signalCode = stageSignal.code();\n if (operationError !== undefined) {\n throw operationError;\n }\n throw new SlackUploadError(\"Slack API returned invalid JSON\", {\n stage,\n status: response.status,\n code: signalCode === \"fetch_failed\" ? \"invalid_json\" : signalCode,\n cause,\n });\n } finally {\n stageSignal.cleanup();\n }\n\n const slackCode = getSlackErrorCode(payload);\n if (!response.ok || !isRecord(payload) || payload[\"ok\"] !== true) {\n throw new SlackUploadError(\"Slack API rejected the request\", {\n stage,\n status: response.status,\n code: slackCode ?? (response.ok ? \"invalid_response\" : `http_${String(response.status)}`),\n retryAfterMs: retryAfterMs(response),\n });\n }\n return payload;\n }\n}\n\nfunction resolveUploaderOptions(\n options: FetchSlackUploaderOptions,\n): ResolvedFetchSlackUploaderOptions {\n assertKnownPlainObject(\n options,\n [\"token\", \"fetch\", \"channelId\", \"requestTimeoutMs\", \"waitForProcessing\", \"poll\"],\n \"FetchSlackUploader options\",\n );\n let token: unknown;\n let fetcher: unknown;\n let channelId: unknown;\n let requestTimeoutMs: unknown;\n let waitForProcessing: unknown;\n let poll: unknown;\n try {\n token = Reflect.get(options, \"token\");\n fetcher = Reflect.get(options, \"fetch\");\n channelId = Reflect.get(options, \"channelId\");\n requestTimeoutMs = Reflect.get(options, \"requestTimeoutMs\");\n waitForProcessing = Reflect.get(options, \"waitForProcessing\");\n poll = Reflect.get(options, \"poll\");\n } catch (cause) {\n throw invalidUploaderOptions(\"Uploader options could not be read\", cause);\n }\n if (typeof token !== \"string\" || token.length === 0 || token !== token.trim()) {\n throw invalidUploaderOptions(\"token must be a nonempty trimmed string\");\n }\n if (\n channelId !== undefined &&\n (typeof channelId !== \"string\" || channelId.length === 0 || channelId !== channelId.trim())\n ) {\n throw invalidUploaderOptions(\"channelId must be a nonempty trimmed string\");\n }\n if (fetcher !== undefined && typeof fetcher !== \"function\") {\n throw invalidUploaderOptions(\"fetch must be a function\");\n }\n if (\n requestTimeoutMs !== undefined &&\n (typeof requestTimeoutMs !== \"number\" ||\n !Number.isFinite(requestTimeoutMs) ||\n requestTimeoutMs <= 0)\n ) {\n throw invalidUploaderOptions(\"requestTimeoutMs must be positive\");\n }\n if (waitForProcessing !== undefined && typeof waitForProcessing !== \"boolean\") {\n throw invalidUploaderOptions(\"waitForProcessing must be boolean\");\n }\n\n const resolvedPoll = resolvePollOptions(poll);\n return {\n token,\n fetcher: (fetcher as SlackFetch | undefined) ?? defaultFetch,\n channelId: channelId as string | undefined,\n requestTimeoutMs: (requestTimeoutMs as number | undefined) ?? DEFAULT_REQUEST_TIMEOUT_MS,\n waitForProcessing: (waitForProcessing as boolean | undefined) ?? false,\n pollIntervalMs: resolvedPoll.intervalMs,\n pollMaxAttempts: resolvedPoll.maxAttempts,\n pollTimeoutMs: resolvedPoll.timeoutMs,\n sleep: resolvedPoll.sleep,\n clock: resolvedPoll.clock,\n };\n}\n\nfunction resolvePollOptions(poll: unknown): {\n readonly intervalMs: number;\n readonly maxAttempts: number;\n readonly timeoutMs: number;\n readonly sleep: SlackUploadSleep;\n readonly clock: SlackUploadClock;\n} {\n if (poll === undefined) {\n return {\n intervalMs: DEFAULT_POLL_INTERVAL_MS,\n maxAttempts: DEFAULT_POLL_MAX_ATTEMPTS,\n timeoutMs: DEFAULT_POLL_TIMEOUT_MS,\n sleep: defaultSleep,\n clock: defaultClock,\n };\n }\n assertKnownPlainObject(\n poll,\n [\"intervalMs\", \"maxAttempts\", \"timeoutMs\", \"sleep\", \"clock\"],\n \"poll options\",\n );\n let intervalMs: unknown;\n let maxAttempts: unknown;\n let timeoutMs: unknown;\n let sleep: unknown;\n let clock: unknown;\n try {\n intervalMs = Reflect.get(poll, \"intervalMs\");\n maxAttempts = Reflect.get(poll, \"maxAttempts\");\n timeoutMs = Reflect.get(poll, \"timeoutMs\");\n sleep = Reflect.get(poll, \"sleep\");\n clock = Reflect.get(poll, \"clock\");\n } catch (cause) {\n throw invalidUploaderOptions(\"poll options could not be read\", cause);\n }\n const resolvedInterval = (intervalMs as number | undefined) ?? DEFAULT_POLL_INTERVAL_MS;\n const resolvedAttempts = (maxAttempts as number | undefined) ?? DEFAULT_POLL_MAX_ATTEMPTS;\n const resolvedTimeout = (timeoutMs as number | undefined) ?? DEFAULT_POLL_TIMEOUT_MS;\n if (!Number.isInteger(resolvedInterval) || resolvedInterval < 0) {\n throw invalidUploaderOptions(\"poll.intervalMs must be a non-negative integer\");\n }\n if (!Number.isInteger(resolvedAttempts) || resolvedAttempts <= 0) {\n throw invalidUploaderOptions(\"poll.maxAttempts must be a positive integer\");\n }\n if (!Number.isFinite(resolvedTimeout) || resolvedTimeout <= 0) {\n throw invalidUploaderOptions(\"poll.timeoutMs must be positive\");\n }\n if (sleep !== undefined && typeof sleep !== \"function\") {\n throw invalidUploaderOptions(\"poll.sleep must be a function\");\n }\n if (clock !== undefined && typeof clock !== \"function\") {\n throw invalidUploaderOptions(\"poll.clock must be a function\");\n }\n return {\n intervalMs: resolvedInterval,\n maxAttempts: resolvedAttempts,\n timeoutMs: resolvedTimeout,\n sleep: (sleep as SlackUploadSleep | undefined) ?? defaultSleep,\n clock: (clock as SlackUploadClock | undefined) ?? defaultClock,\n };\n}\n\nfunction assertKnownPlainObject(\n value: unknown,\n allowed: ReadonlyArray<string>,\n label: string,\n): asserts value is object {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n throw invalidUploaderOptions(`${label} must be a plain object`);\n }\n let prototype: object | null;\n let keys: ReadonlyArray<string>;\n try {\n prototype = Object.getPrototypeOf(value);\n keys = Object.keys(value);\n } catch (cause) {\n throw invalidUploaderOptions(`${label} could not be inspected`, cause);\n }\n if (prototype !== Object.prototype && prototype !== null) {\n throw invalidUploaderOptions(`${label} must be a plain object`);\n }\n const allowedKeys = new Set(allowed);\n for (const key of keys) {\n if (!allowedKeys.has(key)) {\n throw invalidUploaderOptions(`Unknown ${label} key: ${key}`);\n }\n }\n}\n\nfunction invalidUploaderOptions(message: string, cause?: unknown): ConfigurationError {\n return new ConfigurationError(message, {\n code: \"invalid_slack_uploader_options\",\n stage: \"configuration\",\n cause,\n });\n}\n\nfunction encodeForm(fields: ReadonlyArray<readonly [string, string]>): string {\n return fields\n .map(([name, value]) => `${encodeURIComponent(name)}=${encodeURIComponent(value)}`)\n .join(\"&\");\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction isNonEmptyString(value: unknown): value is string {\n return typeof value === \"string\" && value.length > 0;\n}\n\nfunction isPositiveNumber(value: unknown): value is number {\n return typeof value === \"number\" && Number.isFinite(value) && value > 0;\n}\n\nfunction isProcessedImageFile(value: unknown): boolean {\n if (!isRecord(value)) {\n return false;\n }\n return (\n isNonEmptyString(value[\"mimetype\"]) &&\n isNonEmptyString(value[\"filetype\"]) &&\n isPositiveNumber(value[\"original_w\"]) &&\n isPositiveNumber(value[\"original_h\"])\n );\n}\n\nfunction getSlackErrorCode(payload: unknown): string | undefined {\n if (!isRecord(payload)) {\n return undefined;\n }\n const error = payload[\"error\"];\n return typeof error === \"string\" ? error : undefined;\n}\n\nfunction processingTimeout(receipt: UploadReceipt, attempts: number): SlackUploadError {\n return new SlackUploadError(\n `Slack file processing did not complete after ${String(attempts)} polls`,\n {\n stage: SlackUploadStage.ProcessingTimeout,\n code: \"processing_timeout\",\n receipt: slackReceipt({\n ...receipt,\n processing: UploadProcessing.Unverified,\n providerCode: \"processing_timeout\",\n }),\n },\n );\n}\n\n/**\n * Subclass identity is as bundle-sensitive as the base class, so discriminate on `code`.\n */\nfunction isOperationDeadline(error: unknown): boolean {\n return isOperationError(error) && error.code === OperationErrorCode.DeadlineExceeded;\n}\n\ninterface StageSignal {\n readonly signal: AbortSignal;\n cleanup(): void;\n code(): \"aborted\" | \"request_timeout\" | \"fetch_failed\";\n operationError(stage: string, cause: unknown): OperationError | undefined;\n}\n\nfunction createStageSignal(\n control: OperationContext,\n requestTimeoutMs: number,\n clock: SlackUploadClock,\n): StageSignal {\n const controller = new AbortController();\n let timeoutKind: \"operation\" | \"request\" | undefined;\n const abortFromCaller = (): void => {\n controller.abort(control.signal?.reason);\n };\n if (control.signal?.aborted === true) {\n abortFromCaller();\n } else {\n control.signal?.addEventListener(\"abort\", abortFromCaller, { once: true });\n }\n const requestDeadlineMs = clock() + requestTimeoutMs;\n const operationDeadlineMs = control.deadlineMs ?? Number.POSITIVE_INFINITY;\n const stageDeadline = Math.min(requestDeadlineMs, operationDeadlineMs);\n const remaining = Math.max(0, stageDeadline - clock());\n const timeout = setTimeout(() => {\n timeoutKind = operationDeadlineMs <= requestDeadlineMs ? \"operation\" : \"request\";\n controller.abort(new Error(\"Slack request deadline exceeded\"));\n }, remaining);\n return {\n signal: controller.signal,\n cleanup: (): void => {\n clearTimeout(timeout);\n control.signal?.removeEventListener(\"abort\", abortFromCaller);\n },\n code: (): \"aborted\" | \"request_timeout\" | \"fetch_failed\" => {\n if (timeoutKind !== undefined) {\n return \"request_timeout\";\n }\n return control.signal?.aborted === true ? \"aborted\" : \"fetch_failed\";\n },\n operationError: (stage: string, cause: unknown): OperationError | undefined => {\n if (control.signal?.aborted === true) {\n return new OperationAbortedError(stage, { cause });\n }\n if (timeoutKind === \"operation\") {\n return new OperationDeadlineExceededError(stage, { cause });\n }\n return undefined;\n },\n };\n}\n\nfunction controlledSleep(\n sleep: SlackUploadSleep,\n milliseconds: number,\n control: OperationContext,\n clock: SlackUploadClock,\n): Promise<void> {\n if (control.signal?.aborted === true) {\n return Promise.reject(\n new OperationAbortedError(SlackUploadStage.ProcessingTimeout, {\n cause: control.signal.reason,\n }),\n );\n }\n if (control.deadlineMs !== undefined && clock() >= control.deadlineMs) {\n return Promise.reject(new OperationDeadlineExceededError(SlackUploadStage.ProcessingTimeout));\n }\n return new Promise<void>((resolve, reject) => {\n const onAbort = (): void => {\n cleanup();\n reject(\n new OperationAbortedError(SlackUploadStage.ProcessingTimeout, {\n cause: control.signal?.reason,\n }),\n );\n };\n const onDeadline = (): void => {\n cleanup();\n reject(new OperationDeadlineExceededError(SlackUploadStage.ProcessingTimeout));\n };\n const deadlineTimer =\n control.deadlineMs === undefined\n ? undefined\n : setTimeout(onDeadline, Math.max(0, control.deadlineMs - clock()));\n const cleanup = (): void => {\n if (deadlineTimer !== undefined) {\n clearTimeout(deadlineTimer);\n }\n control.signal?.removeEventListener(\"abort\", onAbort);\n };\n control.signal?.addEventListener(\"abort\", onAbort, { once: true });\n void sleep(milliseconds).then(\n () => {\n cleanup();\n resolve();\n return undefined;\n },\n (error: unknown) => {\n cleanup();\n reject(error);\n return undefined;\n },\n );\n });\n}\n\nfunction raceWithSignal<T>(promise: Promise<T>, signal: AbortSignal): Promise<T> {\n if (signal.aborted) {\n return Promise.reject(signal.reason);\n }\n return new Promise<T>((resolve, reject) => {\n const onAbort = (): void => {\n signal.removeEventListener(\"abort\", onAbort);\n reject(signal.reason);\n };\n signal.addEventListener(\"abort\", onAbort, { once: true });\n void promise.then(\n (value) => {\n signal.removeEventListener(\"abort\", onAbort);\n resolve(value);\n return undefined;\n },\n (error: unknown) => {\n signal.removeEventListener(\"abort\", onAbort);\n reject(error);\n return undefined;\n },\n );\n });\n}\n\nfunction slackReceipt(options: {\n readonly phase: UploadReceipt[\"phase\"];\n readonly fileId?: string | undefined;\n readonly shared?: boolean | undefined;\n readonly processing: UploadReceipt[\"processing\"];\n readonly status?: number | undefined;\n readonly retryAfterMs?: number | undefined;\n readonly providerCode?: string | undefined;\n readonly retrySafety?: UploadReceipt[\"retrySafety\"] | undefined;\n}): UploadReceipt {\n return Object.freeze({\n kind: \"upload\",\n provider: \"slack\",\n phase: options.phase,\n fileId: options.fileId,\n shared: options.shared ?? false,\n processing: options.processing,\n status: options.status,\n retryAfterMs: options.retryAfterMs,\n providerCode: options.providerCode,\n retrySafety: options.retrySafety ?? RetrySafety.Never,\n });\n}\n\nfunction withReceipt(error: SlackUploadError, receipt: UploadReceipt): SlackUploadError {\n return new SlackUploadError(error.message, {\n stage: error.stage,\n status: error.status,\n code: error.code,\n retryable: error.retryable,\n retryAfterMs: error.retryAfterMs,\n receipt: slackReceipt({\n ...receipt,\n status: error.status,\n retryAfterMs: error.retryAfterMs,\n providerCode: error.code,\n retrySafety:\n receipt.phase === UploadPhase.Requested\n ? RetrySafety.Safe\n : receipt.phase === UploadPhase.Completed || receipt.phase === UploadPhase.Shared\n ? RetrySafety.Never\n : RetrySafety.MayDuplicate,\n }),\n cause: error.cause,\n });\n}\n\nfunction retryAfterMs(response: SlackFetchResponse): number | undefined {\n const raw = response.headers?.get(\"retry-after\");\n if (raw === undefined || raw === null) {\n return undefined;\n }\n const seconds = Number(raw);\n return Number.isFinite(seconds) && seconds >= 0 ? seconds * 1_000 : undefined;\n}\n\nfunction defaultFetch(input: string, init: SlackFetchRequestInit): Promise<SlackFetchResponse> {\n return globalThis.fetch(input, init);\n}\n\nfunction defaultSleep(milliseconds: number): Promise<void> {\n return new Promise((resolve) => {\n setTimeout(resolve, milliseconds);\n });\n}\n\nfunction defaultClock(): number {\n return Date.now();\n}\n"],"mappings":";AAAA,MAAa,cAAc;CACzB,WAAW;CACX,WAAW;CACX,UAAU;CACV,WAAW;CACX,QAAQ;CACR,SAAS;AACX;AAIA,MAAa,mBAAmB;CAC9B,cAAc;CACd,SAAS;CACT,UAAU;CACV,YAAY;AACd;AAIA,MAAa,cAAc;CACzB,OAAO;CACP,MAAM;CACN,cAAc;AAChB;;;;;;;;;;;;ACbA,MAAM,wBAAwB,OAAO,IAAI,+BAA+B;AAExE,MAAM,4BAA4B,OAAO,IAAI,+BAA+B;AAC5E,MAAM,wBAAwB,OAAO,IAAI,2BAA2B;;;;;AAMpE,SAAgB,oBAAoB,WAAmB,OAAqB;CAC1E,OAAO,eAAe,WAAW,OAAO;EACtC,cAAc;EACd,YAAY;EACZ,OAAO;EACP,UAAU;CACZ,CAAC;AACH;;;;AAKA,SAAgB,cAAc,OAAgB,OAAwB;CACpE,IAAI,OAAO,UAAU,YAAY,UAAU,MACzC,OAAO;CAET,IAAI;EACF,OAAO,QAAQ,IAAI,OAAO,KAAK,MAAM;CACvC,QAAQ;EACN,OAAO;CACT;AACF;AAaA,IAAa,qBAAb,cAAwC,MAAM;CAC5C;EACE,oBAAoB,KAAK,WAAW,yBAAyB;CAC/D;CAEA;CACA;CACA;CACA;CACA;CACA;CAEA,YAAY,SAAiB,UAAqC,CAAC,GAAG;EACpE,MAAM,SAAS,SAAS,UAAU,KAAA,IAAY,EAAE,OAAO,QAAQ,MAAM,IAAI,KAAA,CAAS;EAClF,KAAK,OAAO;EACZ,KAAK,OAAO,QAAQ,QAAQ;EAC5B,KAAK,QAAQ,QAAQ;EACrB,KAAK,YAAY;EACjB,KAAK,WAAW,eAAe,QAAQ,YAAY,CAAC,CAAC;EACrD,KAAK,kBAAkB,QAAQ,mBAAmB,QAAQ,QAAQ,KAAK,QAAQ;CACjF;AACF;AAEA,MAAa,qBAAqB;CAChC,SAAS;CACT,kBAAkB;CAClB,UAAU;AACZ;;;;AAaA,IAAa,iBAAb,cAAoC,MAAM;CACxC;EACE,oBAAoB,KAAK,WAAW,qBAAqB;CAC3D;CAEA;CACA;CACA;CACA;CACA;CACA;CAEA,YACE,SACA,MACA,OACA,WACA,UAAiC,CAAC,GAClC;EACA,MAAM,SAAS,QAAQ,UAAU,KAAA,IAAY,EAAE,OAAO,QAAQ,MAAM,IAAI,KAAA,CAAS;EACjF,KAAK,OAAO;EACZ,KAAK,OAAO;EACZ,KAAK,QAAQ;EACb,KAAK,YAAY;EACjB,KAAK,WAAW,eAAe,QAAQ,YAAY,CAAC,CAAC;EACrD,KAAK,kBAAkB,QAAQ,mBAAmB,QAAQ,QAAQ,KAAK,QAAQ;CACjF;AACF;AAEA,IAAa,wBAAb,cAA2C,eAAe;CACxD;CAEA,YAAY,OAAe,UAAiC,CAAC,GAAG;EAC9D,MAAM,+BAA+B,mBAAmB,SAAS,OAAO,OAAO,OAAO;EACtF,KAAK,OAAO;CACd;AACF;AAEA,IAAa,iCAAb,cAAoD,eAAe;CACjE;CAEA,YAAY,OAAe,UAAiC,CAAC,GAAG;EAC9D,MAAM,+BAA+B,mBAAmB,kBAAkB,OAAO,MAAM,OAAO;EAC9F,KAAK,OAAO;CACd;AACF;;;;;;;;;;AA+BA,SAAgB,iBAAiB,OAAyC;CACxE,OAAO,cAAc,OAAO,qBAAqB;AACnD;AA4CA,SAAgB,eACd,OACA,UACA,iBACS;CACT,IAAI,EAAE,iBAAiB,QACrB,OAAO;CAET,IAAI;EACF,IAAI,QAAQ,IAAI,OAAO,qBAAqB,MAAM,MAChD,OAAO;CAEX,QAAQ;EACN,OAAO;CACT;CACA,IAAI,WAAyC,CAAC;CAC9C,IAAI;EACF,MAAM,YAAY,QAAQ,IAAI,OAAO,UAAU;EAC/C,IAAI,MAAM,QAAQ,SAAS,GACzB,WAAW,UAAU,OAAO,eAAe;CAE/C,QAAQ;EACN,WAAW,CAAC;CACd;CACA,QAAQ,eAAe,OAAO,YAAY;EACxC,cAAc;EACd,YAAY;EACZ,OAAO,eAAe,cAAc,UAAU,QAAQ,CAAC;EACvD,UAAU;CACZ,CAAC;CACD,IAAI,oBAAoB,KAAA,GAAW;EACjC,MAAM,gBAAgB,sBAAsB,iBAAiB,QAAQ;EACrE,QAAQ,eAAe,OAAO,mBAAmB;GAC/C,cAAc;GACd,YAAY;GACZ,OAAO;GACP,UAAU;EACZ,CAAC;CACH;CACA,OAAO;AACT;AAcA,eAAe,sBACb,iBACA,UACuC;CACvC,IAAI;EACF,OAAO,eAAe,MAAM,eAAe;CAC7C,QAAQ;EACN,OAAO,eAAe,QAAQ;CAChC;AACF;AAEA,SAAS,cACP,UACA,UAC8B;CAC9B,MAAM,iBAAiB,cAAc,QAAQ;CAC7C,MAAM,iBAAiB,cAAc,QAAQ;CAC7C,MAAM,SAA0B,CAAC,GAAG,QAAQ;CAC5C,KAAK,MAAM,CAAC,KAAK,WAAW,gBAAgB;EAC1C,MAAM,UAAU,eAAe,IAAI,GAAG,CAAC,EAAE,UAAU;EACnD,IAAI,OAAO,SAAS,SAClB,OAAO,KAAK,GAAG,OAAO,MAAM,OAAO,CAAC;CAExC;CACA,OAAO;AACT;AAEA,SAAS,cACP,UACmD;CACnD,MAAM,0BAAU,IAAI,IAA6B;CACjD,KAAK,MAAM,WAAW,UAAU;EAC9B,MAAM,MAAM,WAAW,OAAO;EAC9B,MAAM,SAAS,QAAQ,IAAI,GAAG;EAC9B,IAAI,WAAW,KAAA,GACb,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC;OAE1B,OAAO,KAAK,OAAO;CAEvB;CACA,OAAO;AACT;AAEA,SAAS,WAAW,SAAgC;CAClD,OAAO;EACL,QAAQ;EACR,QAAQ;EACR,QAAQ,UAAU;EAClB,OAAO,QAAQ,MAAM;EACrB,QAAQ;EACR,OAAO,QAAQ,UAAU,EAAE;EAC3B,OAAO,QAAQ,gBAAgB,EAAE;EACjC,QAAQ,gBAAgB;EACxB,QAAQ;CACV,CAAC,CAAC,KAAK,IAAQ;AACjB;AAEA,SAAS,eAAe,UAAsE;CAC5F,OAAO,OAAO,OAAO,SAAS,KAAK,YAAY,OAAO,OAAO,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC;AAC/E;AAEA,SAAS,gBAAgB,OAAwC;CAC/D,OAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,QAAQ,IAAI,OAAO,MAAM,MAAM;AACvF;;;;ACzUA,MAAM,2BAA2B,OAAO,IAAI,6BAA6B;AAEzE,MAAa,mBAAmB;CAC9B,WAAW;CACX,cAAc;CACd,aAAa;CACb,gBAAgB;CAChB,UAAU;CACV,mBAAmB;AACrB;;;;AAiBA,IAAa,mBAAb,cAAsC,MAAM;CAC1C;EACE,oBAAoB,KAAK,WAAW,wBAAwB;CAC9D;CAEA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CAEA,YAAY,SAAiB,SAAkC;EAC7D,MAAM,SAAS,QAAQ,UAAU,KAAA,IAAY,EAAE,OAAO,QAAQ,MAAM,IAAI,KAAA,CAAS;EACjF,KAAK,OAAO;EACZ,KAAK,QAAQ,QAAQ;EACrB,KAAK,SAAS,QAAQ;EACtB,KAAK,OAAO,QAAQ;EACpB,KAAK,YAAY,QAAQ,aAAa,YAAY,QAAQ,QAAQ,QAAQ,IAAI;EAC9E,KAAK,eAAe,QAAQ;EAC5B,KAAK,UAAU,OAAO,OACpB,QAAQ,WAAW;GACjB,MAAM;GACN,UAAU;GACV,OAAO,YAAY;GACnB,QAAQ,KAAA;GACR,QAAQ;GACR,YAAY,iBAAiB;GAC7B,QAAQ,QAAQ;GAChB,cAAc,QAAQ;GACtB,cAAc,QAAQ;GACtB,aAAa,YAAY;EAC3B,CACF;EACA,KAAK,WAAW,OAAO,OAAO,CAAC,KAAK,OAAO,CAAC;EAC5C,KAAK,kBAAkB,QAAQ,QAAQ,KAAK,QAAQ;CACtD;AACF;;;;;;AAOA,SAAgB,mBAAmB,OAA2C;CAC5E,OAAO,cAAc,OAAO,wBAAwB;AACtD;AAEA,SAAS,YAAY,QAA4B,MAAmC;CAClF,OACE,WAAW,OACV,WAAW,KAAA,KAAa,UAAU,OACnC,SAAS,kBACT,SAAS,qBACT,SAAS;AAEb;;;AC/DA,MAAM,qBAAqB;AAC3B,MAAM,2BAA2B;AACjC,MAAM,4BAA4B;AAClC,MAAM,0BAA0B;AAChC,MAAM,6BAA6B;;;;;;AAgEnC,IAAa,qBAAb,MAAyD;CACvD;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CAEA,YAAY,SAAoC;EAC9C,MAAM,WAAW,uBAAuB,OAAO;EAC/C,KAAK,QAAQ,SAAS;EACtB,KAAK,UAAU,SAAS;EACxB,KAAK,YAAY,SAAS;EAC1B,KAAK,mBAAmB,SAAS;EACjC,KAAK,oBAAoB,SAAS;EAClC,KAAK,iBAAiB,SAAS;EAC/B,KAAK,kBAAkB,SAAS;EAChC,KAAK,gBAAgB,SAAS;EAC9B,KAAK,QAAQ,SAAS;EACtB,KAAK,QAAQ,SAAS;CACxB;CAEA,MAAM,OACJ,KACA,SACuE;EACvE,IAAI,UAAU,aAAa;GACzB,OAAO,YAAY;GACnB,YAAY,iBAAiB;GAC7B,aAAa,YAAY;EAC3B,CAAC;EACD,IAAI;GACF,MAAM,SAAS,MAAM,KAAK,gBAAgB,KAAK,OAAO;GACtD,UAAU,aAAa;IACrB,OAAO,YAAY;IACnB,QAAQ,OAAO;IACf,YAAY,iBAAiB;IAC7B,aAAa,YAAY;GAC3B,CAAC;GACD,MAAM,KAAK,YAAY,QAAQ,KAAK,OAAO;GAC3C,UAAU,aAAa;IACrB,OAAO,YAAY;IACnB,QAAQ,OAAO;IACf,YAAY,iBAAiB;IAC7B,aAAa,YAAY;GAC3B,CAAC;GACD,MAAM,KAAK,eAAe,OAAO,QAAQ,IAAI,UAAU,OAAO;GAC9D,UAAU,aAAa;IACrB,OAAO,KAAK,cAAc,KAAA,IAAY,YAAY,YAAY,YAAY;IAC1E,QAAQ,OAAO;IACf,QAAQ,KAAK,cAAc,KAAA;IAC3B,YAAY,KAAK,oBACb,iBAAiB,UACjB,iBAAiB;IACrB,aAAa,YAAY;GAC3B,CAAC;GACD,IAAI,KAAK,mBACP,IAAI;IACF,MAAM,KAAK,mBAAmB,OAAO,QAAQ,SAAS,OAAO;IAC7D,UAAU,aAAa;KACrB,GAAG;KACH,YAAY,iBAAiB;IAC/B,CAAC;GACH,SAAS,OAAO;IACd,IAAI,iBAAiB,KAAK,GACxB,MAAM,eAAe,OAAO,CAAC,OAAO,CAAC;IAEvC,IAAI,mBAAmB,KAAK,GAC1B,UAAU,aAAa;KACrB,GAAG;KACH,YAAY,iBAAiB;KAC7B,QAAQ,MAAM;KACd,cAAc,MAAM;KACpB,cAAc,MAAM;IACtB,CAAC;SAED,UAAU,aAAa;KACrB,GAAG;KACH,YAAY,iBAAiB;KAC7B,cAAc;IAChB,CAAC;GAEL;GAEF,OAAO;IAAE,QAAQ,OAAO;IAAQ;GAAQ;EAC1C,SAAS,OAAO;GACd,IAAI,mBAAmB,KAAK,GAC1B,MAAM,YAAY,OAAO,OAAO;GAElC,IAAI,iBAAiB,KAAK,GACxB,MAAM,eAAe,OAAO,CAAC,OAAO,CAAC;GAEvC,MAAM;EACR;CACF;CAEA,MAAc,gBAAgB,KAAiB,SAAkD;EAC/F,MAAM,UAAU,MAAM,KAAK,aACzB,8BACA,WAAW,CACT,CAAC,YAAY,IAAI,QAAQ,GACzB,CAAC,UAAU,OAAO,IAAI,KAAK,UAAU,CAAC,CACxC,CAAC,GACD,iBAAiB,cACjB,OACF;EACA,MAAM,YAAY,QAAQ;EAC1B,MAAM,SAAS,QAAQ;EACvB,IAAI,CAAC,iBAAiB,SAAS,KAAK,CAAC,iBAAiB,MAAM,GAC1D,MAAM,IAAI,iBAAiB,gEAAgE;GACzF,OAAO,iBAAiB;GACxB,MAAM;EACR,CAAC;EAEH,OAAO;GAAE;GAAW;EAAO;CAC7B;CAEA,MAAc,YACZ,QACA,KACA,SACe;EACf,MAAM,cAAc,kBAAkB,SAAS,KAAK,kBAAkB,KAAK,KAAK;EAChF,IAAI;EACJ,IAAI;GACF,WAAW,MAAM,KAAK,QAAQ,OAAO,WAAW;IAC9C,QAAQ;IACR,SAAS,EAAE,gBAAgB,IAAI,SAAS;IACxC,MAAM,IAAI;IACV,QAAQ,YAAY;GACtB,CAAC;EACH,SAAS,OAAO;GACd,MAAM,iBAAiB,YAAY,eAAe,iBAAiB,aAAa,KAAK;GACrF,IAAI,mBAAmB,KAAA,GACrB,MAAM;GAER,MAAM,IAAI,iBAAiB,4BAA4B;IACrD,OAAO,iBAAiB;IACxB,MAAM,YAAY,KAAK;IACvB;GACF,CAAC;EACH,UAAU;GACR,YAAY,QAAQ;EACtB;EACA,IAAI,CAAC,SAAS,IACZ,MAAM,IAAI,iBAAiB,kCAAkC;GAC3D,OAAO,iBAAiB;GACxB,QAAQ,SAAS;GACjB,MAAM,QAAQ,OAAO,SAAS,MAAM;GACpC,cAAc,aAAa,QAAQ;EACrC,CAAC;CAEL;CAEA,MAAc,eACZ,QACA,UACA,SACe;EACf,MAAM,SAA2C,CAC/C,CACE,SACA,KAAK,UAAU,CACb;GACE,IAAI;GACJ,OAAO;EACT,CACF,CAAC,CACH,CACF;EACA,IAAI,KAAK,cAAc,KAAA,GACrB,OAAO,KAAK,CAAC,cAAc,KAAK,SAAS,CAAC;EAE5C,MAAM,KAAK,aACT,gCACA,WAAW,MAAM,GACjB,iBAAiB,gBACjB,OACF;CACF;CAEA,MAAc,mBACZ,QACA,SACA,SACe;EACf,MAAM,YAAY,KAAK,MAAM;EAC7B,MAAM,iBAAiB,YAAY,KAAK;EACxC,MAAM,mBACJ,QAAQ,eAAe,KAAA,KAAa,iBAAiB,QAAQ;EAC/D,MAAM,cAAgC;GACpC,QAAQ,QAAQ;GAChB,YAAY,KAAK,IAAI,QAAQ,cAAc,OAAO,mBAAmB,cAAc;EACrF;EAEA,KAAK,IAAI,UAAU,GAAG,WAAW,KAAK,iBAAiB,WAAW,GAAG;GACnE,IAAI,KAAK,MAAM,KAAK,gBAClB,MAAM,kBAAkB,SAAS,UAAU,CAAC;GAE9C,IAAI;GACJ,IAAI;IACF,UAAU,MAAM,KAAK,aACnB,cACA,WAAW,CAAC,CAAC,QAAQ,MAAM,CAAC,CAAC,GAC7B,iBAAiB,UACjB,WACF;GACF,SAAS,OAAO;IACd,IAAI,oBAAoB,oBAAoB,KAAK,GAC/C,MAAM,kBAAkB,SAAS,OAAO;IAE1C,MAAM;GACR;GACA,IAAI,qBAAqB,QAAQ,OAAO,GACtC;GAGF,IAAI,YAAY,KAAK,mBAAmB,KAAK,MAAM,IAAI,aAAa,KAAK,eACvE,MAAM,kBAAkB,SAAS,OAAO;GAG1C,IAAI;IACF,MAAM,gBACJ,KAAK,OACL,KAAK,IAAI,KAAK,gBAAgB,KAAK,IAAI,GAAG,iBAAiB,KAAK,MAAM,CAAC,CAAC,GACxE,aACA,KAAK,KACP;GACF,SAAS,OAAO;IACd,IAAI,oBAAoB,oBAAoB,KAAK,GAC/C,MAAM,kBAAkB,SAAS,OAAO;IAE1C,MAAM;GACR;GAEA,IAAI,KAAK,MAAM,IAAI,aAAa,KAAK,eACnC,MAAM,kBAAkB,SAAS,OAAO;EAE5C;CACF;CAEA,MAAc,aACZ,QACA,MACA,OACA,SACkC;EAClC,MAAM,cAAc,kBAAkB,SAAS,KAAK,kBAAkB,KAAK,KAAK;EAChF,IAAI;EACJ,IAAI;GACF,WAAW,MAAM,KAAK,QAAQ,GAAG,mBAAmB,GAAG,UAAU;IAC/D,QAAQ;IACR,SAAS;KACP,eAAe,UAAU,KAAK;KAC9B,gBAAgB;IAClB;IACA;IACA,QAAQ,YAAY;GACtB,CAAC;EACH,SAAS,OAAO;GACd,MAAM,iBAAiB,YAAY,eAAe,OAAO,KAAK;GAC9D,YAAY,QAAQ;GACpB,IAAI,mBAAmB,KAAA,GACrB,MAAM;GAER,MAAM,IAAI,iBAAiB,4BAA4B;IACrD;IACA,MAAM,YAAY,KAAK;IACvB;GACF,CAAC;EACH;EAEA,IAAI;EACJ,IAAI;GACF,UAAU,MAAM,eAAe,SAAS,KAAK,GAAG,YAAY,MAAM;EACpE,SAAS,OAAO;GACd,MAAM,iBAAiB,YAAY,eAAe,OAAO,KAAK;GAC9D,MAAM,aAAa,YAAY,KAAK;GACpC,IAAI,mBAAmB,KAAA,GACrB,MAAM;GAER,MAAM,IAAI,iBAAiB,mCAAmC;IAC5D;IACA,QAAQ,SAAS;IACjB,MAAM,eAAe,iBAAiB,iBAAiB;IACvD;GACF,CAAC;EACH,UAAU;GACR,YAAY,QAAQ;EACtB;EAEA,MAAM,YAAY,kBAAkB,OAAO;EAC3C,IAAI,CAAC,SAAS,MAAM,CAAC,SAAS,OAAO,KAAK,QAAQ,UAAU,MAC1D,MAAM,IAAI,iBAAiB,kCAAkC;GAC3D;GACA,QAAQ,SAAS;GACjB,MAAM,cAAc,SAAS,KAAK,qBAAqB,QAAQ,OAAO,SAAS,MAAM;GACrF,cAAc,aAAa,QAAQ;EACrC,CAAC;EAEH,OAAO;CACT;AACF;AAEA,SAAS,uBACP,SACmC;CACnC,uBACE,SACA;EAAC;EAAS;EAAS;EAAa;EAAoB;EAAqB;CAAM,GAC/E,4BACF;CACA,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;EACF,QAAQ,QAAQ,IAAI,SAAS,OAAO;EACpC,UAAU,QAAQ,IAAI,SAAS,OAAO;EACtC,YAAY,QAAQ,IAAI,SAAS,WAAW;EAC5C,mBAAmB,QAAQ,IAAI,SAAS,kBAAkB;EAC1D,oBAAoB,QAAQ,IAAI,SAAS,mBAAmB;EAC5D,OAAO,QAAQ,IAAI,SAAS,MAAM;CACpC,SAAS,OAAO;EACd,MAAM,uBAAuB,sCAAsC,KAAK;CAC1E;CACA,IAAI,OAAO,UAAU,YAAY,MAAM,WAAW,KAAK,UAAU,MAAM,KAAK,GAC1E,MAAM,uBAAuB,yCAAyC;CAExE,IACE,cAAc,KAAA,MACb,OAAO,cAAc,YAAY,UAAU,WAAW,KAAK,cAAc,UAAU,KAAK,IAEzF,MAAM,uBAAuB,6CAA6C;CAE5E,IAAI,YAAY,KAAA,KAAa,OAAO,YAAY,YAC9C,MAAM,uBAAuB,0BAA0B;CAEzD,IACE,qBAAqB,KAAA,MACpB,OAAO,qBAAqB,YAC3B,CAAC,OAAO,SAAS,gBAAgB,KACjC,oBAAoB,IAEtB,MAAM,uBAAuB,mCAAmC;CAElE,IAAI,sBAAsB,KAAA,KAAa,OAAO,sBAAsB,WAClE,MAAM,uBAAuB,mCAAmC;CAGlE,MAAM,eAAe,mBAAmB,IAAI;CAC5C,OAAO;EACL;EACA,SAAU,WAAsC;EACrC;EACX,kBAAmB,oBAA2C;EAC9D,mBAAoB,qBAA6C;EACjE,gBAAgB,aAAa;EAC7B,iBAAiB,aAAa;EAC9B,eAAe,aAAa;EAC5B,OAAO,aAAa;EACpB,OAAO,aAAa;CACtB;AACF;AAEA,SAAS,mBAAmB,MAM1B;CACA,IAAI,SAAS,KAAA,GACX,OAAO;EACL,YAAY;EACZ,aAAa;EACb,WAAW;EACX,OAAO;EACP,OAAO;CACT;CAEF,uBACE,MACA;EAAC;EAAc;EAAe;EAAa;EAAS;CAAO,GAC3D,cACF;CACA,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;EACF,aAAa,QAAQ,IAAI,MAAM,YAAY;EAC3C,cAAc,QAAQ,IAAI,MAAM,aAAa;EAC7C,YAAY,QAAQ,IAAI,MAAM,WAAW;EACzC,QAAQ,QAAQ,IAAI,MAAM,OAAO;EACjC,QAAQ,QAAQ,IAAI,MAAM,OAAO;CACnC,SAAS,OAAO;EACd,MAAM,uBAAuB,kCAAkC,KAAK;CACtE;CACA,MAAM,mBAAoB,cAAqC;CAC/D,MAAM,mBAAoB,eAAsC;CAChE,MAAM,kBAAmB,aAAoC;CAC7D,IAAI,CAAC,OAAO,UAAU,gBAAgB,KAAK,mBAAmB,GAC5D,MAAM,uBAAuB,gDAAgD;CAE/E,IAAI,CAAC,OAAO,UAAU,gBAAgB,KAAK,oBAAoB,GAC7D,MAAM,uBAAuB,6CAA6C;CAE5E,IAAI,CAAC,OAAO,SAAS,eAAe,KAAK,mBAAmB,GAC1D,MAAM,uBAAuB,iCAAiC;CAEhE,IAAI,UAAU,KAAA,KAAa,OAAO,UAAU,YAC1C,MAAM,uBAAuB,+BAA+B;CAE9D,IAAI,UAAU,KAAA,KAAa,OAAO,UAAU,YAC1C,MAAM,uBAAuB,+BAA+B;CAE9D,OAAO;EACL,YAAY;EACZ,aAAa;EACb,WAAW;EACX,OAAQ,SAA0C;EAClD,OAAQ,SAA0C;CACpD;AACF;AAEA,SAAS,uBACP,OACA,SACA,OACyB;CACzB,IAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,MAAM,QAAQ,KAAK,GACpE,MAAM,uBAAuB,GAAG,MAAM,wBAAwB;CAEhE,IAAI;CACJ,IAAI;CACJ,IAAI;EACF,YAAY,OAAO,eAAe,KAAK;EACvC,OAAO,OAAO,KAAK,KAAK;CAC1B,SAAS,OAAO;EACd,MAAM,uBAAuB,GAAG,MAAM,0BAA0B,KAAK;CACvE;CACA,IAAI,cAAc,OAAO,aAAa,cAAc,MAClD,MAAM,uBAAuB,GAAG,MAAM,wBAAwB;CAEhE,MAAM,cAAc,IAAI,IAAI,OAAO;CACnC,KAAK,MAAM,OAAO,MAChB,IAAI,CAAC,YAAY,IAAI,GAAG,GACtB,MAAM,uBAAuB,WAAW,MAAM,QAAQ,KAAK;AAGjE;AAEA,SAAS,uBAAuB,SAAiB,OAAqC;CACpF,OAAO,IAAI,mBAAmB,SAAS;EACrC,MAAM;EACN,OAAO;EACP;CACF,CAAC;AACH;AAEA,SAAS,WAAW,QAA0D;CAC5E,OAAO,OACJ,KAAK,CAAC,MAAM,WAAW,GAAG,mBAAmB,IAAI,EAAE,GAAG,mBAAmB,KAAK,GAAG,CAAC,CAClF,KAAK,GAAG;AACb;AAEA,SAAS,SAAS,OAAkD;CAClE,OAAO,OAAO,UAAU,YAAY,UAAU;AAChD;AAEA,SAAS,iBAAiB,OAAiC;CACzD,OAAO,OAAO,UAAU,YAAY,MAAM,SAAS;AACrD;AAEA,SAAS,iBAAiB,OAAiC;CACzD,OAAO,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,KAAK,QAAQ;AACxE;AAEA,SAAS,qBAAqB,OAAyB;CACrD,IAAI,CAAC,SAAS,KAAK,GACjB,OAAO;CAET,OACE,iBAAiB,MAAM,WAAW,KAClC,iBAAiB,MAAM,WAAW,KAClC,iBAAiB,MAAM,aAAa,KACpC,iBAAiB,MAAM,aAAa;AAExC;AAEA,SAAS,kBAAkB,SAAsC;CAC/D,IAAI,CAAC,SAAS,OAAO,GACnB;CAEF,MAAM,QAAQ,QAAQ;CACtB,OAAO,OAAO,UAAU,WAAW,QAAQ,KAAA;AAC7C;AAEA,SAAS,kBAAkB,SAAwB,UAAoC;CACrF,OAAO,IAAI,iBACT,gDAAgD,OAAO,QAAQ,EAAE,SACjE;EACE,OAAO,iBAAiB;EACxB,MAAM;EACN,SAAS,aAAa;GACpB,GAAG;GACH,YAAY,iBAAiB;GAC7B,cAAc;EAChB,CAAC;CACH,CACF;AACF;;;;AAKA,SAAS,oBAAoB,OAAyB;CACpD,OAAO,iBAAiB,KAAK,KAAK,MAAM,SAAS,mBAAmB;AACtE;AASA,SAAS,kBACP,SACA,kBACA,OACa;CACb,MAAM,aAAa,IAAI,gBAAgB;CACvC,IAAI;CACJ,MAAM,wBAA8B;EAClC,WAAW,MAAM,QAAQ,QAAQ,MAAM;CACzC;CACA,IAAI,QAAQ,QAAQ,YAAY,MAC9B,gBAAgB;MAEhB,QAAQ,QAAQ,iBAAiB,SAAS,iBAAiB,EAAE,MAAM,KAAK,CAAC;CAE3E,MAAM,oBAAoB,MAAM,IAAI;CACpC,MAAM,sBAAsB,QAAQ,cAAc,OAAO;CAEzD,MAAM,YAAY,KAAK,IAAI,GADL,KAAK,IAAI,mBAAmB,mBACR,IAAI,MAAM,CAAC;CACrD,MAAM,UAAU,iBAAiB;EAC/B,cAAc,uBAAuB,oBAAoB,cAAc;EACvE,WAAW,sBAAM,IAAI,MAAM,iCAAiC,CAAC;CAC/D,GAAG,SAAS;CACZ,OAAO;EACL,QAAQ,WAAW;EACnB,eAAqB;GACnB,aAAa,OAAO;GACpB,QAAQ,QAAQ,oBAAoB,SAAS,eAAe;EAC9D;EACA,YAA4D;GAC1D,IAAI,gBAAgB,KAAA,GAClB,OAAO;GAET,OAAO,QAAQ,QAAQ,YAAY,OAAO,YAAY;EACxD;EACA,iBAAiB,OAAe,UAA+C;GAC7E,IAAI,QAAQ,QAAQ,YAAY,MAC9B,OAAO,IAAI,sBAAsB,OAAO,EAAE,MAAM,CAAC;GAEnD,IAAI,gBAAgB,aAClB,OAAO,IAAI,+BAA+B,OAAO,EAAE,MAAM,CAAC;EAG9D;CACF;AACF;AAEA,SAAS,gBACP,OACA,cACA,SACA,OACe;CACf,IAAI,QAAQ,QAAQ,YAAY,MAC9B,OAAO,QAAQ,OACb,IAAI,sBAAsB,iBAAiB,mBAAmB,EAC5D,OAAO,QAAQ,OAAO,OACxB,CAAC,CACH;CAEF,IAAI,QAAQ,eAAe,KAAA,KAAa,MAAM,KAAK,QAAQ,YACzD,OAAO,QAAQ,OAAO,IAAI,+BAA+B,iBAAiB,iBAAiB,CAAC;CAE9F,OAAO,IAAI,SAAe,SAAS,WAAW;EAC5C,MAAM,gBAAsB;GAC1B,QAAQ;GACR,OACE,IAAI,sBAAsB,iBAAiB,mBAAmB,EAC5D,OAAO,QAAQ,QAAQ,OACzB,CAAC,CACH;EACF;EACA,MAAM,mBAAyB;GAC7B,QAAQ;GACR,OAAO,IAAI,+BAA+B,iBAAiB,iBAAiB,CAAC;EAC/E;EACA,MAAM,gBACJ,QAAQ,eAAe,KAAA,IACnB,KAAA,IACA,WAAW,YAAY,KAAK,IAAI,GAAG,QAAQ,aAAa,MAAM,CAAC,CAAC;EACtE,MAAM,gBAAsB;GAC1B,IAAI,kBAAkB,KAAA,GACpB,aAAa,aAAa;GAE5B,QAAQ,QAAQ,oBAAoB,SAAS,OAAO;EACtD;EACA,QAAQ,QAAQ,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;EACjE,MAAW,YAAY,CAAC,CAAC,WACjB;GACJ,QAAQ;GACR,QAAQ;EAEV,IACC,UAAmB;GAClB,QAAQ;GACR,OAAO,KAAK;EAEd,CACF;CACF,CAAC;AACH;AAEA,SAAS,eAAkB,SAAqB,QAAiC;CAC/E,IAAI,OAAO,SACT,OAAO,QAAQ,OAAO,OAAO,MAAM;CAErC,OAAO,IAAI,SAAY,SAAS,WAAW;EACzC,MAAM,gBAAsB;GAC1B,OAAO,oBAAoB,SAAS,OAAO;GAC3C,OAAO,OAAO,MAAM;EACtB;EACA,OAAO,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;EACxD,QAAa,MACV,UAAU;GACT,OAAO,oBAAoB,SAAS,OAAO;GAC3C,QAAQ,KAAK;EAEf,IACC,UAAmB;GAClB,OAAO,oBAAoB,SAAS,OAAO;GAC3C,OAAO,KAAK;EAEd,CACF;CACF,CAAC;AACH;AAEA,SAAS,aAAa,SASJ;CAChB,OAAO,OAAO,OAAO;EACnB,MAAM;EACN,UAAU;EACV,OAAO,QAAQ;EACf,QAAQ,QAAQ;EAChB,QAAQ,QAAQ,UAAU;EAC1B,YAAY,QAAQ;EACpB,QAAQ,QAAQ;EAChB,cAAc,QAAQ;EACtB,cAAc,QAAQ;EACtB,aAAa,QAAQ,eAAe,YAAY;CAClD,CAAC;AACH;AAEA,SAAS,YAAY,OAAyB,SAA0C;CACtF,OAAO,IAAI,iBAAiB,MAAM,SAAS;EACzC,OAAO,MAAM;EACb,QAAQ,MAAM;EACd,MAAM,MAAM;EACZ,WAAW,MAAM;EACjB,cAAc,MAAM;EACpB,SAAS,aAAa;GACpB,GAAG;GACH,QAAQ,MAAM;GACd,cAAc,MAAM;GACpB,cAAc,MAAM;GACpB,aACE,QAAQ,UAAU,YAAY,YAC1B,YAAY,OACZ,QAAQ,UAAU,YAAY,aAAa,QAAQ,UAAU,YAAY,SACvE,YAAY,QACZ,YAAY;EACtB,CAAC;EACD,OAAO,MAAM;CACf,CAAC;AACH;AAEA,SAAS,aAAa,UAAkD;CACtE,MAAM,MAAM,SAAS,SAAS,IAAI,aAAa;CAC/C,IAAI,QAAQ,KAAA,KAAa,QAAQ,MAC/B;CAEF,MAAM,UAAU,OAAO,GAAG;CAC1B,OAAO,OAAO,SAAS,OAAO,KAAK,WAAW,IAAI,UAAU,MAAQ,KAAA;AACtE;AAEA,SAAS,aAAa,OAAe,MAA0D;CAC7F,OAAO,WAAW,MAAM,OAAO,IAAI;AACrC;AAEA,SAAS,aAAa,cAAqC;CACzD,OAAO,IAAI,SAAS,YAAY;EAC9B,WAAW,SAAS,YAAY;CAClC,CAAC;AACH;AAEA,SAAS,eAAuB;CAC9B,OAAO,KAAK,IAAI;AAClB"}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import type { Root } from "mdast";
|
|
2
2
|
import type { Block } from "./blocks/types.js";
|
|
3
3
|
import type { CapabilityFlags, CapabilityFlagsPartial, CapabilityPresetName } from "./capabilities/capabilities.js";
|
|
4
|
+
import type { UploadReceipt } from "./receipts.js";
|
|
5
|
+
export { RetrySafety, UploadPhase, UploadProcessing } from "./receipts.js";
|
|
6
|
+
export type { UploadReceipt } from "./receipts.js";
|
|
4
7
|
/**
|
|
5
8
|
* Structured degradation emitted when content falls back or is truncated.
|
|
6
9
|
*/
|
|
@@ -10,6 +13,17 @@ export interface Degradation {
|
|
|
10
13
|
readonly to: string;
|
|
11
14
|
readonly reason: string;
|
|
12
15
|
readonly path: string;
|
|
16
|
+
readonly details?: DegradationDetails | undefined;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Optional machine-readable context for a degradation. The core fields above
|
|
20
|
+
* remain stable and sufficient for human-readable fallback reporting.
|
|
21
|
+
*/
|
|
22
|
+
export interface DegradationDetails {
|
|
23
|
+
readonly code?: string | undefined;
|
|
24
|
+
readonly stage?: string | undefined;
|
|
25
|
+
readonly retryable?: boolean | undefined;
|
|
26
|
+
readonly rendererId?: string | undefined;
|
|
13
27
|
}
|
|
14
28
|
/**
|
|
15
29
|
* Total conversion result — never throws on user markdown.
|
|
@@ -18,6 +32,7 @@ export interface ConversionResult {
|
|
|
18
32
|
readonly blocks: ReadonlyArray<Block>;
|
|
19
33
|
readonly text: string;
|
|
20
34
|
readonly degradations: ReadonlyArray<Degradation>;
|
|
35
|
+
readonly receipts: ReadonlyArray<UploadReceipt>;
|
|
21
36
|
}
|
|
22
37
|
/**
|
|
23
38
|
* One message chunk from multi-message conversion.
|
|
@@ -32,6 +47,7 @@ export interface ConversionMessage {
|
|
|
32
47
|
export interface ConversionMessagesResult {
|
|
33
48
|
readonly messages: ReadonlyArray<ConversionMessage>;
|
|
34
49
|
readonly degradations: ReadonlyArray<Degradation>;
|
|
50
|
+
readonly receipts: ReadonlyArray<UploadReceipt>;
|
|
35
51
|
}
|
|
36
52
|
export declare const OverflowMode: {
|
|
37
53
|
readonly Degrade: "degrade";
|
|
@@ -44,7 +60,8 @@ export declare const ConversionStrategy: {
|
|
|
44
60
|
};
|
|
45
61
|
export type ConversionStrategy = (typeof ConversionStrategy)[keyof typeof ConversionStrategy];
|
|
46
62
|
/**
|
|
47
|
-
*
|
|
63
|
+
* Normalized fenced content passed to {@link ImageRenderer}. Display math uses
|
|
64
|
+
* `lang: "math"`; fenced-code languages are lowercase and trimmed.
|
|
48
65
|
*/
|
|
49
66
|
export interface RenderRequest {
|
|
50
67
|
readonly lang: string;
|
|
@@ -56,35 +73,86 @@ export type BytesImage = {
|
|
|
56
73
|
readonly data: Uint8Array;
|
|
57
74
|
readonly mimeType: "image/png" | "image/jpeg" | "image/gif";
|
|
58
75
|
readonly filename: string;
|
|
76
|
+
readonly altText?: string | undefined;
|
|
59
77
|
};
|
|
60
78
|
export type UrlImage = {
|
|
61
79
|
readonly kind: "url";
|
|
62
80
|
readonly imageUrl: string;
|
|
81
|
+
readonly altText?: string | undefined;
|
|
63
82
|
};
|
|
64
83
|
export type RenderedImage = UrlImage | BytesImage;
|
|
65
84
|
/**
|
|
66
|
-
*
|
|
85
|
+
* Safe machine-readable renderer failure metadata. Implementations must keep
|
|
86
|
+
* untrusted source and collaborator messages out of these fields.
|
|
67
87
|
*/
|
|
68
|
-
export interface
|
|
88
|
+
export interface StructuredRendererError {
|
|
89
|
+
readonly code: string;
|
|
90
|
+
readonly stage: string;
|
|
91
|
+
readonly retryable: boolean;
|
|
92
|
+
readonly rendererId?: string | undefined;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Pluggable image renderer for Mermaid fences that cannot become native
|
|
96
|
+
* charts, display math, and generic code fences.
|
|
97
|
+
*
|
|
98
|
+
* Renderers are consulted in configuration order. {@link canRender} should be
|
|
99
|
+
* a cheap, synchronous capability check; conversion calls {@link render} only
|
|
100
|
+
* after it returns true. Return `null` to decline a request after inspection.
|
|
101
|
+
* Attempt failures are buffered while conversion tries later renderers. A
|
|
102
|
+
* later success emits no failure degradation; only an all-failed chain records
|
|
103
|
+
* the buffered failures before text fallback. URL output must be an absolute
|
|
104
|
+
* HTTPS URL without credentials and within Slack's image URL limit.
|
|
105
|
+
*/
|
|
106
|
+
export declare const ImageRendererOutput: {
|
|
107
|
+
readonly Url: "url";
|
|
108
|
+
readonly Bytes: "bytes";
|
|
109
|
+
readonly Both: "both";
|
|
110
|
+
};
|
|
111
|
+
export type ImageRendererOutput = (typeof ImageRendererOutput)[keyof typeof ImageRendererOutput];
|
|
112
|
+
export type RendererImage<TOutput extends ImageRendererOutput> = TOutput extends "url" ? UrlImage : TOutput extends "bytes" ? BytesImage : RenderedImage;
|
|
113
|
+
export interface ImageRenderer<TOutput extends ImageRendererOutput = ImageRendererOutput> {
|
|
114
|
+
/** Stable machine-readable renderer identity. */
|
|
115
|
+
readonly id: string;
|
|
116
|
+
/** Declared output contract, enforced against every non-null result. */
|
|
117
|
+
readonly output: TOutput;
|
|
118
|
+
/** Whether this renderer accepts the normalized language and request. */
|
|
69
119
|
canRender(req: RenderRequest): boolean;
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
120
|
+
/** Produce an image or return `null` to let the next renderer try. */
|
|
121
|
+
render(req: RenderRequest, context: OperationContext): Promise<RendererImage<TOutput> | null>;
|
|
122
|
+
}
|
|
123
|
+
export type UrlImageRenderer = ImageRenderer<"url">;
|
|
124
|
+
export type BytesImageRenderer = ImageRenderer<"bytes">;
|
|
125
|
+
export type BothImageRenderer = ImageRenderer<"both">;
|
|
126
|
+
/**
|
|
127
|
+
* Ergonomic high-level operation bounds.
|
|
128
|
+
*/
|
|
129
|
+
export interface OperationOptions {
|
|
130
|
+
readonly signal?: AbortSignal | undefined;
|
|
131
|
+
/** Relative milliseconds from call start. */
|
|
132
|
+
readonly timeoutMs?: number | undefined;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Absolute context passed only to execution collaborators.
|
|
136
|
+
*/
|
|
137
|
+
export interface OperationContext {
|
|
138
|
+
readonly signal: AbortSignal | undefined;
|
|
139
|
+
readonly deadlineMs: number | undefined;
|
|
73
140
|
}
|
|
74
141
|
/**
|
|
75
142
|
* Uploads bytes-producing renderer output to Slack files API.
|
|
76
143
|
*/
|
|
77
144
|
export interface SlackUploader {
|
|
78
|
-
upload(img: BytesImage): Promise<{
|
|
145
|
+
upload(img: BytesImage, context: OperationContext): Promise<{
|
|
79
146
|
readonly fileId: string;
|
|
147
|
+
readonly receipt: UploadReceipt;
|
|
80
148
|
}>;
|
|
81
149
|
}
|
|
82
150
|
/**
|
|
83
151
|
* Optional mention resolvers (off by default).
|
|
84
152
|
*/
|
|
85
153
|
export interface MentionResolvers {
|
|
86
|
-
readonly resolveUser?: (handle: string) => string | undefined;
|
|
87
|
-
readonly resolveChannel?: (name: string) => string | undefined;
|
|
154
|
+
readonly resolveUser?: ((handle: string) => string | undefined) | undefined;
|
|
155
|
+
readonly resolveChannel?: ((name: string) => string | undefined) | undefined;
|
|
88
156
|
}
|
|
89
157
|
/**
|
|
90
158
|
* Public conversion options (per-call).
|
|
@@ -98,8 +166,17 @@ export interface ConvertOptions {
|
|
|
98
166
|
readonly renderers?: ReadonlyArray<ImageRenderer> | undefined;
|
|
99
167
|
readonly uploader?: SlackUploader | undefined;
|
|
100
168
|
readonly enableMath?: boolean | undefined;
|
|
169
|
+
/**
|
|
170
|
+
* Treat `$x$` inside a paragraph as inline math. Off by default even when
|
|
171
|
+
* {@link ConversionOptions.enableMath} is on, because agent prose is far more likely to
|
|
172
|
+
* contain currency (`$200/mo versus $350/mo`) than inline LaTeX, and reading the span
|
|
173
|
+
* between two dollar signs as math deletes both signs. `$$…$$` is unaffected.
|
|
174
|
+
*/
|
|
175
|
+
readonly enableInlineMath?: boolean | undefined;
|
|
101
176
|
readonly enableFrontmatter?: boolean | undefined;
|
|
102
177
|
readonly mentionResolvers?: MentionResolvers | undefined;
|
|
178
|
+
readonly signal?: AbortSignal | undefined;
|
|
179
|
+
readonly timeoutMs?: number | undefined;
|
|
103
180
|
}
|
|
104
181
|
/**
|
|
105
182
|
* Collects degradations during a single conversion.
|
|
@@ -108,6 +185,12 @@ export interface DegradationCollector {
|
|
|
108
185
|
add(d: Degradation): void;
|
|
109
186
|
all(): ReadonlyArray<Degradation>;
|
|
110
187
|
}
|
|
188
|
+
export interface ReceiptCollector {
|
|
189
|
+
add(receipt: UploadReceipt): void;
|
|
190
|
+
all(): ReadonlyArray<UploadReceipt>;
|
|
191
|
+
settle(): void;
|
|
192
|
+
settled(): Promise<ReadonlyArray<UploadReceipt>>;
|
|
193
|
+
}
|
|
111
194
|
/**
|
|
112
195
|
* Budget reservation claimed while planning a candidate.
|
|
113
196
|
*/
|
|
@@ -153,6 +236,7 @@ export interface MarkdownParser {
|
|
|
153
236
|
}
|
|
154
237
|
export interface ParserOptions {
|
|
155
238
|
readonly enableMath: boolean;
|
|
239
|
+
readonly enableInlineMath: boolean;
|
|
156
240
|
readonly enableFrontmatter: boolean;
|
|
157
241
|
}
|
|
158
242
|
/**
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;AAElC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,KAAK,EACV,eAAe,EACf,sBAAsB,EACtB,oBAAoB,EACrB,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;AAElC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,KAAK,EACV,eAAe,EACf,sBAAsB,EACtB,oBAAoB,EACrB,MAAM,gCAAgC,CAAC;AACxC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAC3E,YAAY,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,SAAS,CAAC;CACnD;AAED;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACzC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC1C;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC;IACtC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,YAAY,EAAE,aAAa,CAAC,WAAW,CAAC,CAAC;IAClD,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC,aAAa,CAAC,CAAC;CACjD;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC;IACtC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC,iBAAiB,CAAC,CAAC;IACpD,QAAQ,CAAC,YAAY,EAAE,aAAa,CAAC,WAAW,CAAC,CAAC;IAClD,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC,aAAa,CAAC,CAAC;CACjD;AAED,eAAO,MAAM,YAAY;aACvB,OAAO,EAAE,SAAS;aAClB,KAAK,EAAE,OAAO;CACN,CAAC;AAEX,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,OAAO,YAAY,CAAC,CAAC;AAE5E,eAAO,MAAM,kBAAkB;aAC7B,aAAa,EAAE,iBAAiB;aAChC,aAAa,EAAE,gBAAgB;CACvB,CAAC;AAEX,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,OAAO,kBAAkB,CAAC,CAAC;AAE9F;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,WAAW,GAAG,YAAY,GAAG,WAAW,CAAC;IAC5D,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACvC,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG;IACrB,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IACrB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACvC,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,UAAU,CAAC;AAElD;;;GAGG;AACH,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC1C;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,mBAAmB;aAC9B,GAAG,EAAE,KAAK;aACV,KAAK,EAAE,OAAO;aACd,IAAI,EAAE,MAAM;CACJ,CAAC;AAEX,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,OAAO,mBAAmB,CAAC,CAAC;AAEjG,MAAM,MAAM,aAAa,CAAC,OAAO,SAAS,mBAAmB,IAAI,OAAO,SAAS,KAAK,GAClF,QAAQ,GACR,OAAO,SAAS,OAAO,GACrB,UAAU,GACV,aAAa,CAAC;AAEpB,MAAM,WAAW,aAAa,CAAC,OAAO,SAAS,mBAAmB,GAAG,mBAAmB;IACtF,iDAAiD;IACjD,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,wEAAwE;IACxE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,yEAAyE;IACzE,SAAS,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC;IACvC,sEAAsE;IACtE,MAAM,CAAC,GAAG,EAAE,aAAa,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;CAC/F;AAED,MAAM,MAAM,gBAAgB,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;AACpD,MAAM,MAAM,kBAAkB,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;AACxD,MAAM,MAAM,iBAAiB,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;AAEtD;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;IAC1C,6CAA6C;IAC7C,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACzC;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,SAAS,CAAC;IACzC,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;CACzC;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,MAAM,CACJ,GAAG,EAAE,UAAU,EACf,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC;QAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAA;KAAE,CAAC,CAAC;CAC1E;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC,GAAG,SAAS,CAAC;IAC5E,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC,GAAG,SAAS,CAAC;CAC9E;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,YAAY,CAAC,EAClB,oBAAoB,GACpB,eAAe,GACf,sBAAsB,GACtB,SAAS,CAAC;IACd,QAAQ,CAAC,mBAAmB,CAAC,EAAE,sBAAsB,GAAG,SAAS,CAAC;IAClE,QAAQ,CAAC,QAAQ,CAAC,EAAE,YAAY,GAAG,SAAS,CAAC;IAC7C,QAAQ,CAAC,QAAQ,CAAC,EAAE,kBAAkB,GAAG,SAAS,CAAC;IACnD,QAAQ,CAAC,SAAS,CAAC,EAAE,aAAa,CAAC,aAAa,CAAC,GAAG,SAAS,CAAC;IAC9D,QAAQ,CAAC,QAAQ,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;IAC9C,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC1C;;;;;OAKG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAChD,QAAQ,CAAC,iBAAiB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACjD,QAAQ,CAAC,gBAAgB,CAAC,EAAE,gBAAgB,GAAG,SAAS,CAAC;IACzD,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;IAC1C,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACzC;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,GAAG,CAAC,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IAC1B,GAAG,IAAI,aAAa,CAAC,WAAW,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,gBAAgB;IAC/B,GAAG,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI,CAAC;IAClC,GAAG,IAAI,aAAa,CAAC,aAAa,CAAC,CAAC;IACpC,MAAM,IAAI,IAAI,CAAC;IACf,OAAO,IAAI,OAAO,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC,CAAC;CAClD;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,eAAe,CAAC,KAAK,EAAE,WAAW,GAAG,SAAS,GAAG,OAAO,CAAC;IACzD,QAAQ,IAAI,cAAc,CAAC;IAC3B,+EAA+E;IAC/E,OAAO,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI,CAAC;IACxC,kBAAkB,IAAI,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC;IACjC,gBAAgB,CAAC,MAAM,EAAE,aAAa,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC;CACxD;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAChE;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC;IACnC,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAC;CACrC;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,kBAAkB,CAAC;CAC3C;AAED,MAAM,MAAM,kBAAkB,GAC1B;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,iBAAiB,CAAA;CAAE,GACxE;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpD,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACtF;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,QAAQ,CAAC,UAAU,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAC3C,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC;IACpD,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC;CACtD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate-blocks.d.ts","sourceRoot":"","sources":["../../src/validate/validate-blocks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,
|
|
1
|
+
{"version":3,"file":"validate-blocks.d.ts","sourceRoot":"","sources":["../../src/validate/validate-blocks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAA6C,MAAM,oBAAoB,CAAC;AAwB3F,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,OAAO,CAAC,MAAM,oBAAoB,EAAE,OAAO,MAAM,CAAC;AAElD;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,aAAa,CAAC,KAAK,CAAC,GAAG;IACnD,QAAQ,CAAC,CAAC,oBAAoB,CAAC,EAAE,IAAI,CAAC;CACvC,CAAC;AASF;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,aAAa,CAAC,KAAK,CAAC,GAAG,eAAe,CAmD5E"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "slackmark",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Compile SlackMark (CommonMark and GFM plus Slack extensions) to Slack Block Kit JSON",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"block kit",
|
|
@@ -54,17 +54,18 @@
|
|
|
54
54
|
"devDependencies": {
|
|
55
55
|
"@types/mdast": "^4.0.4",
|
|
56
56
|
"@types/node": "^22.15.30",
|
|
57
|
-
"
|
|
57
|
+
"tsdown": "^0.22.13",
|
|
58
|
+
"unrun": "^0.3.1",
|
|
58
59
|
"vitest": "^4.1.7"
|
|
59
60
|
},
|
|
60
61
|
"engines": {
|
|
61
62
|
"node": "^20.19.0 || >=22.12.0"
|
|
62
63
|
},
|
|
63
64
|
"scripts": {
|
|
64
|
-
"build": "
|
|
65
|
+
"build": "tsdown && tsc -p tsconfig.build.json",
|
|
65
66
|
"test": "vitest run",
|
|
66
67
|
"test:watch": "vitest",
|
|
67
|
-
"typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.test.json --noEmit",
|
|
68
|
+
"typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.test.json --noEmit && tsc -p tsconfig.examples.json --noEmit",
|
|
68
69
|
"typecheck:src": "tsc -p tsconfig.json --noEmit"
|
|
69
70
|
}
|
|
70
71
|
}
|