@chat-adapter/shared 4.1.0 → 4.4.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/dist/index.d.ts +78 -2
- package/dist/index.js +100 -51
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -68,7 +68,7 @@ declare function extractFiles(message: AdapterPostableMessage): FileUpload[];
|
|
|
68
68
|
/**
|
|
69
69
|
* Supported platform names for adapter utilities.
|
|
70
70
|
*/
|
|
71
|
-
type PlatformName = "slack" | "gchat" | "teams";
|
|
71
|
+
type PlatformName = "slack" | "gchat" | "teams" | "discord";
|
|
72
72
|
/**
|
|
73
73
|
* Button style mappings per platform.
|
|
74
74
|
*
|
|
@@ -128,6 +128,82 @@ interface FallbackTextOptions {
|
|
|
128
128
|
*/
|
|
129
129
|
declare function cardToFallbackText(card: CardElement, options?: FallbackTextOptions): string;
|
|
130
130
|
|
|
131
|
+
/**
|
|
132
|
+
* Buffer conversion utilities for handling file uploads.
|
|
133
|
+
*
|
|
134
|
+
* These utilities handle the conversion of various data types
|
|
135
|
+
* (Buffer, ArrayBuffer, Blob) to Node.js Buffer for file uploads.
|
|
136
|
+
*/
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* The supported input types for file data.
|
|
140
|
+
*/
|
|
141
|
+
type FileDataInput = Buffer | ArrayBuffer | Blob;
|
|
142
|
+
/**
|
|
143
|
+
* Options for buffer conversion.
|
|
144
|
+
*/
|
|
145
|
+
interface ToBufferOptions {
|
|
146
|
+
/**
|
|
147
|
+
* The platform name for error messages.
|
|
148
|
+
*/
|
|
149
|
+
platform: PlatformName;
|
|
150
|
+
/**
|
|
151
|
+
* If true, throws ValidationError for unsupported types.
|
|
152
|
+
* If false, returns null for unsupported types.
|
|
153
|
+
* Default: true
|
|
154
|
+
*/
|
|
155
|
+
throwOnUnsupported?: boolean;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Convert various data types to a Node.js Buffer.
|
|
159
|
+
*
|
|
160
|
+
* Handles:
|
|
161
|
+
* - Buffer: returned as-is
|
|
162
|
+
* - ArrayBuffer: converted using Buffer.from()
|
|
163
|
+
* - Blob: converted via arrayBuffer() then Buffer.from()
|
|
164
|
+
*
|
|
165
|
+
* @param data - The file data to convert
|
|
166
|
+
* @param options - Conversion options
|
|
167
|
+
* @returns Buffer or null if conversion fails and throwOnUnsupported is false
|
|
168
|
+
* @throws ValidationError if data type is unsupported and throwOnUnsupported is true
|
|
169
|
+
*
|
|
170
|
+
* @example
|
|
171
|
+
* ```typescript
|
|
172
|
+
* // Throw on unsupported (default behavior)
|
|
173
|
+
* const buffer = await toBuffer(file.data, { platform: "slack" });
|
|
174
|
+
*
|
|
175
|
+
* // Return null on unsupported
|
|
176
|
+
* const buffer = await toBuffer(file.data, { platform: "teams", throwOnUnsupported: false });
|
|
177
|
+
* if (!buffer) continue; // Skip unsupported files
|
|
178
|
+
* ```
|
|
179
|
+
*/
|
|
180
|
+
declare function toBuffer(data: FileDataInput | unknown, options: ToBufferOptions): Promise<Buffer | null>;
|
|
181
|
+
/**
|
|
182
|
+
* Synchronous version of toBuffer for non-Blob data.
|
|
183
|
+
*
|
|
184
|
+
* Use this when you know the data is not a Blob (e.g., already validated).
|
|
185
|
+
*
|
|
186
|
+
* @param data - The file data to convert (Buffer or ArrayBuffer only)
|
|
187
|
+
* @param options - Conversion options
|
|
188
|
+
* @returns Buffer or null if conversion fails
|
|
189
|
+
* @throws ValidationError if data is a Blob or unsupported type and throwOnUnsupported is true
|
|
190
|
+
*/
|
|
191
|
+
declare function toBufferSync(data: Buffer | ArrayBuffer | unknown, options: ToBufferOptions): Buffer | null;
|
|
192
|
+
/**
|
|
193
|
+
* Convert a Buffer to a data URI string.
|
|
194
|
+
*
|
|
195
|
+
* @param buffer - The buffer to convert
|
|
196
|
+
* @param mimeType - The MIME type (default: application/octet-stream)
|
|
197
|
+
* @returns Data URI string in format `data:{mimeType};base64,{base64Data}`
|
|
198
|
+
*
|
|
199
|
+
* @example
|
|
200
|
+
* ```typescript
|
|
201
|
+
* const dataUri = bufferToDataUri(buffer, "image/png");
|
|
202
|
+
* // "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgA..."
|
|
203
|
+
* ```
|
|
204
|
+
*/
|
|
205
|
+
declare function bufferToDataUri(buffer: Buffer, mimeType?: string): string;
|
|
206
|
+
|
|
131
207
|
/**
|
|
132
208
|
* Standardized error types for chat adapters.
|
|
133
209
|
*
|
|
@@ -224,4 +300,4 @@ declare class NetworkError extends AdapterError {
|
|
|
224
300
|
constructor(adapter: string, message?: string, originalError?: Error | undefined);
|
|
225
301
|
}
|
|
226
302
|
|
|
227
|
-
export { AdapterError, AdapterRateLimitError, AuthenticationError, BUTTON_STYLE_MAPPINGS, type FallbackTextOptions, NetworkError, PermissionError, type PlatformName, ResourceNotFoundError, ValidationError, cardToFallbackText, createEmojiConverter, extractCard, extractFiles, mapButtonStyle };
|
|
303
|
+
export { AdapterError, AdapterRateLimitError, AuthenticationError, BUTTON_STYLE_MAPPINGS, type FallbackTextOptions, type FileDataInput, NetworkError, PermissionError, type PlatformName, ResourceNotFoundError, type ToBufferOptions, ValidationError, bufferToDataUri, cardToFallbackText, createEmojiConverter, extractCard, extractFiles, mapButtonStyle, toBuffer, toBufferSync };
|
package/dist/index.js
CHANGED
|
@@ -16,56 +16,6 @@ function extractFiles(message) {
|
|
|
16
16
|
return [];
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
// src/card-utils.ts
|
|
20
|
-
import { convertEmojiPlaceholders } from "chat";
|
|
21
|
-
var BUTTON_STYLE_MAPPINGS = {
|
|
22
|
-
slack: { primary: "primary", danger: "danger" },
|
|
23
|
-
gchat: { primary: "primary", danger: "danger" },
|
|
24
|
-
// Colors handled via buttonColor
|
|
25
|
-
teams: { primary: "positive", danger: "destructive" }
|
|
26
|
-
};
|
|
27
|
-
function createEmojiConverter(platform) {
|
|
28
|
-
return (text) => convertEmojiPlaceholders(text, platform);
|
|
29
|
-
}
|
|
30
|
-
function mapButtonStyle(style, platform) {
|
|
31
|
-
if (!style) return void 0;
|
|
32
|
-
return BUTTON_STYLE_MAPPINGS[platform][style];
|
|
33
|
-
}
|
|
34
|
-
function cardToFallbackText(card, options = {}) {
|
|
35
|
-
const { boldFormat = "*", lineBreak = "\n", platform } = options;
|
|
36
|
-
const convertText = platform ? createEmojiConverter(platform) : (t) => t;
|
|
37
|
-
const parts = [];
|
|
38
|
-
if (card.title) {
|
|
39
|
-
parts.push(`${boldFormat}${convertText(card.title)}${boldFormat}`);
|
|
40
|
-
}
|
|
41
|
-
if (card.subtitle) {
|
|
42
|
-
parts.push(convertText(card.subtitle));
|
|
43
|
-
}
|
|
44
|
-
for (const child of card.children) {
|
|
45
|
-
const text = childToFallbackText(child, convertText);
|
|
46
|
-
if (text) {
|
|
47
|
-
parts.push(text);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
return parts.join(lineBreak);
|
|
51
|
-
}
|
|
52
|
-
function childToFallbackText(child, convertText) {
|
|
53
|
-
switch (child.type) {
|
|
54
|
-
case "text":
|
|
55
|
-
return convertText(child.content);
|
|
56
|
-
case "fields":
|
|
57
|
-
return child.children.map((f) => `${convertText(f.label)}: ${convertText(f.value)}`).join("\n");
|
|
58
|
-
case "actions":
|
|
59
|
-
return `[${child.children.map((b) => convertText(b.label)).join("] [")}]`;
|
|
60
|
-
case "section":
|
|
61
|
-
return child.children.map((c) => childToFallbackText(c, convertText)).filter(Boolean).join("\n");
|
|
62
|
-
case "divider":
|
|
63
|
-
return "---";
|
|
64
|
-
default:
|
|
65
|
-
return null;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
19
|
// src/errors.ts
|
|
70
20
|
var AdapterError = class extends Error {
|
|
71
21
|
/**
|
|
@@ -144,6 +94,102 @@ var NetworkError = class extends AdapterError {
|
|
|
144
94
|
this.name = "NetworkError";
|
|
145
95
|
}
|
|
146
96
|
};
|
|
97
|
+
|
|
98
|
+
// src/buffer-utils.ts
|
|
99
|
+
async function toBuffer(data, options) {
|
|
100
|
+
const { platform, throwOnUnsupported = true } = options;
|
|
101
|
+
if (Buffer.isBuffer(data)) {
|
|
102
|
+
return data;
|
|
103
|
+
}
|
|
104
|
+
if (data instanceof ArrayBuffer) {
|
|
105
|
+
return Buffer.from(data);
|
|
106
|
+
}
|
|
107
|
+
if (data instanceof Blob) {
|
|
108
|
+
const arrayBuffer = await data.arrayBuffer();
|
|
109
|
+
return Buffer.from(arrayBuffer);
|
|
110
|
+
}
|
|
111
|
+
if (throwOnUnsupported) {
|
|
112
|
+
throw new ValidationError(platform, "Unsupported file data type");
|
|
113
|
+
}
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
function toBufferSync(data, options) {
|
|
117
|
+
const { platform, throwOnUnsupported = true } = options;
|
|
118
|
+
if (Buffer.isBuffer(data)) {
|
|
119
|
+
return data;
|
|
120
|
+
}
|
|
121
|
+
if (data instanceof ArrayBuffer) {
|
|
122
|
+
return Buffer.from(data);
|
|
123
|
+
}
|
|
124
|
+
if (data instanceof Blob) {
|
|
125
|
+
if (throwOnUnsupported) {
|
|
126
|
+
throw new ValidationError(
|
|
127
|
+
platform,
|
|
128
|
+
"Cannot convert Blob synchronously. Use toBuffer() for async conversion."
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
if (throwOnUnsupported) {
|
|
134
|
+
throw new ValidationError(platform, "Unsupported file data type");
|
|
135
|
+
}
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
function bufferToDataUri(buffer, mimeType = "application/octet-stream") {
|
|
139
|
+
const base64 = buffer.toString("base64");
|
|
140
|
+
return `data:${mimeType};base64,${base64}`;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// src/card-utils.ts
|
|
144
|
+
import { convertEmojiPlaceholders } from "chat";
|
|
145
|
+
var BUTTON_STYLE_MAPPINGS = {
|
|
146
|
+
slack: { primary: "primary", danger: "danger" },
|
|
147
|
+
gchat: { primary: "primary", danger: "danger" },
|
|
148
|
+
// Colors handled via buttonColor
|
|
149
|
+
teams: { primary: "positive", danger: "destructive" },
|
|
150
|
+
discord: { primary: "primary", danger: "danger" }
|
|
151
|
+
};
|
|
152
|
+
function createEmojiConverter(platform) {
|
|
153
|
+
return (text) => convertEmojiPlaceholders(text, platform);
|
|
154
|
+
}
|
|
155
|
+
function mapButtonStyle(style, platform) {
|
|
156
|
+
if (!style) return void 0;
|
|
157
|
+
return BUTTON_STYLE_MAPPINGS[platform][style];
|
|
158
|
+
}
|
|
159
|
+
function cardToFallbackText(card, options = {}) {
|
|
160
|
+
const { boldFormat = "*", lineBreak = "\n", platform } = options;
|
|
161
|
+
const convertText = platform ? createEmojiConverter(platform) : (t) => t;
|
|
162
|
+
const parts = [];
|
|
163
|
+
if (card.title) {
|
|
164
|
+
parts.push(`${boldFormat}${convertText(card.title)}${boldFormat}`);
|
|
165
|
+
}
|
|
166
|
+
if (card.subtitle) {
|
|
167
|
+
parts.push(convertText(card.subtitle));
|
|
168
|
+
}
|
|
169
|
+
for (const child of card.children) {
|
|
170
|
+
const text = childToFallbackText(child, convertText);
|
|
171
|
+
if (text) {
|
|
172
|
+
parts.push(text);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
return parts.join(lineBreak);
|
|
176
|
+
}
|
|
177
|
+
function childToFallbackText(child, convertText) {
|
|
178
|
+
switch (child.type) {
|
|
179
|
+
case "text":
|
|
180
|
+
return convertText(child.content);
|
|
181
|
+
case "fields":
|
|
182
|
+
return child.children.map((f) => `${convertText(f.label)}: ${convertText(f.value)}`).join("\n");
|
|
183
|
+
case "actions":
|
|
184
|
+
return `[${child.children.map((b) => convertText(b.label)).join("] [")}]`;
|
|
185
|
+
case "section":
|
|
186
|
+
return child.children.map((c) => childToFallbackText(c, convertText)).filter(Boolean).join("\n");
|
|
187
|
+
case "divider":
|
|
188
|
+
return "---";
|
|
189
|
+
default:
|
|
190
|
+
return null;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
147
193
|
export {
|
|
148
194
|
AdapterError,
|
|
149
195
|
AdapterRateLimitError,
|
|
@@ -153,10 +199,13 @@ export {
|
|
|
153
199
|
PermissionError,
|
|
154
200
|
ResourceNotFoundError,
|
|
155
201
|
ValidationError,
|
|
202
|
+
bufferToDataUri,
|
|
156
203
|
cardToFallbackText,
|
|
157
204
|
createEmojiConverter,
|
|
158
205
|
extractCard,
|
|
159
206
|
extractFiles,
|
|
160
|
-
mapButtonStyle
|
|
207
|
+
mapButtonStyle,
|
|
208
|
+
toBuffer,
|
|
209
|
+
toBufferSync
|
|
161
210
|
};
|
|
162
211
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/adapter-utils.ts","../src/card-utils.ts","../src/errors.ts"],"sourcesContent":["/**\n * Shared utility functions for chat adapters.\n *\n * These utilities are used across all adapter implementations (Slack, Teams, GChat)\n * to reduce code duplication and ensure consistent behavior.\n */\n\nimport type { CardElement } from \"chat\";\nimport { isCardElement } from \"chat\";\nimport type { AdapterPostableMessage, FileUpload } from \"chat\";\n\n/**\n * Extract CardElement from an AdapterPostableMessage if present.\n *\n * Handles two cases:\n * 1. The message IS a CardElement (type: \"card\")\n * 2. The message is a PostableCard with a `card` property\n *\n * @param message - The message to extract the card from\n * @returns The CardElement if found, null otherwise\n *\n * @example\n * ```typescript\n * // Case 1: Direct CardElement\n * const card = Card({ title: \"Test\" });\n * extractCard(card); // returns the card\n *\n * // Case 2: PostableCard wrapper\n * const message = { card, fallbackText: \"...\" };\n * extractCard(message); // returns the card\n *\n * // Case 3: Non-card message\n * extractCard(\"Hello\"); // returns null\n * extractCard({ markdown: \"**bold**\" }); // returns null\n * ```\n */\nexport function extractCard(\n message: AdapterPostableMessage,\n): CardElement | null {\n if (isCardElement(message)) {\n return message;\n }\n if (typeof message === \"object\" && message !== null && \"card\" in message) {\n return message.card;\n }\n return null;\n}\n\n/**\n * Extract FileUpload array from an AdapterPostableMessage if present.\n *\n * Files can be attached to PostableRaw, PostableMarkdown, PostableAst,\n * or PostableCard messages via the `files` property.\n *\n * @param message - The message to extract files from\n * @returns Array of FileUpload objects, or empty array if none\n *\n * @example\n * ```typescript\n * // With files\n * const message = {\n * markdown: \"**Text**\",\n * files: [{ data: Buffer.from(\"...\"), filename: \"doc.pdf\" }]\n * };\n * extractFiles(message); // returns the files array\n *\n * // Without files\n * extractFiles(\"Hello\"); // returns []\n * extractFiles({ raw: \"text\" }); // returns []\n * ```\n */\nexport function extractFiles(message: AdapterPostableMessage): FileUpload[] {\n if (typeof message === \"object\" && message !== null && \"files\" in message) {\n return (message as { files?: FileUpload[] }).files ?? [];\n }\n return [];\n}\n","/**\n * Shared card conversion utilities for adapters.\n *\n * These utilities reduce duplication across adapter implementations\n * for card-to-platform-format conversions.\n */\n\nimport type { ButtonElement, CardChild, CardElement } from \"chat\";\nimport { convertEmojiPlaceholders } from \"chat\";\n\n/**\n * Supported platform names for adapter utilities.\n */\nexport type PlatformName = \"slack\" | \"gchat\" | \"teams\";\n\n/**\n * Button style mappings per platform.\n *\n * Maps our standard button styles (\"primary\", \"danger\") to\n * platform-specific values.\n */\nexport const BUTTON_STYLE_MAPPINGS: Record<\n PlatformName,\n Record<string, string>\n> = {\n slack: { primary: \"primary\", danger: \"danger\" },\n gchat: { primary: \"primary\", danger: \"danger\" }, // Colors handled via buttonColor\n teams: { primary: \"positive\", danger: \"destructive\" },\n};\n\n/**\n * Create a platform-specific emoji converter function.\n *\n * Returns a function that converts emoji placeholders (e.g., `{{emoji:wave}}`)\n * to the platform's native format.\n *\n * @example\n * ```typescript\n * const convertEmoji = createEmojiConverter(\"slack\");\n * convertEmoji(\"{{emoji:wave}} Hello\"); // \":wave: Hello\"\n * ```\n */\nexport function createEmojiConverter(\n platform: PlatformName,\n): (text: string) => string {\n return (text: string) => convertEmojiPlaceholders(text, platform);\n}\n\n/**\n * Map a button style to the platform-specific value.\n *\n * @example\n * ```typescript\n * mapButtonStyle(\"primary\", \"teams\"); // \"positive\"\n * mapButtonStyle(\"danger\", \"slack\"); // \"danger\"\n * mapButtonStyle(undefined, \"teams\"); // undefined\n * ```\n */\nexport function mapButtonStyle(\n style: ButtonElement[\"style\"],\n platform: PlatformName,\n): string | undefined {\n if (!style) return undefined;\n return BUTTON_STYLE_MAPPINGS[platform][style];\n}\n\n/**\n * Options for fallback text generation.\n */\nexport interface FallbackTextOptions {\n /** Bold format string (default: \"*\" for mrkdwn, \"**\" for markdown) */\n boldFormat?: \"*\" | \"**\";\n /** Line break between sections (default: \"\\n\") */\n lineBreak?: \"\\n\" | \"\\n\\n\";\n /** Platform for emoji conversion (optional) */\n platform?: PlatformName;\n}\n\n/**\n * Generate fallback plain text from a card element.\n *\n * Used when the platform can't render rich cards or for notification previews.\n * Consolidates duplicate implementations from individual adapters.\n *\n * @example\n * ```typescript\n * // Slack-style (mrkdwn)\n * cardToFallbackText(card, { boldFormat: \"*\", platform: \"slack\" });\n *\n * // Teams-style (markdown with double line breaks)\n * cardToFallbackText(card, { boldFormat: \"**\", lineBreak: \"\\n\\n\", platform: \"teams\" });\n * ```\n */\nexport function cardToFallbackText(\n card: CardElement,\n options: FallbackTextOptions = {},\n): string {\n const { boldFormat = \"*\", lineBreak = \"\\n\", platform } = options;\n\n const convertText = platform\n ? createEmojiConverter(platform)\n : (t: string) => t;\n\n const parts: string[] = [];\n\n if (card.title) {\n parts.push(`${boldFormat}${convertText(card.title)}${boldFormat}`);\n }\n\n if (card.subtitle) {\n parts.push(convertText(card.subtitle));\n }\n\n for (const child of card.children) {\n const text = childToFallbackText(child, convertText);\n if (text) {\n parts.push(text);\n }\n }\n\n return parts.join(lineBreak);\n}\n\n/**\n * Convert a card child element to fallback text.\n * Internal helper for cardToFallbackText.\n */\nfunction childToFallbackText(\n child: CardChild,\n convertText: (t: string) => string,\n): string | null {\n switch (child.type) {\n case \"text\":\n return convertText(child.content);\n case \"fields\":\n return child.children\n .map((f) => `${convertText(f.label)}: ${convertText(f.value)}`)\n .join(\"\\n\");\n case \"actions\":\n return `[${child.children.map((b) => convertText(b.label)).join(\"] [\")}]`;\n case \"section\":\n return child.children\n .map((c) => childToFallbackText(c, convertText))\n .filter(Boolean)\n .join(\"\\n\");\n case \"divider\":\n return \"---\";\n default:\n return null;\n }\n}\n","/**\n * Standardized error types for chat adapters.\n *\n * These error classes provide consistent error handling across all\n * adapter implementations.\n */\n\n/**\n * Base error class for adapter operations.\n *\n * All adapter-specific errors should extend this class.\n */\nexport class AdapterError extends Error {\n /**\n * @param message - Human-readable error message\n * @param adapter - Name of the adapter (e.g., \"slack\", \"teams\", \"gchat\")\n * @param code - Optional error code for programmatic handling\n */\n constructor(\n message: string,\n public readonly adapter: string,\n public readonly code?: string,\n ) {\n super(message);\n this.name = \"AdapterError\";\n }\n}\n\n/**\n * Rate limit error - thrown when platform API rate limits are hit.\n *\n * @example\n * ```typescript\n * throw new AdapterRateLimitError(\"slack\", 30);\n * // message: \"Rate limited by slack, retry after 30s\"\n * ```\n */\nexport class AdapterRateLimitError extends AdapterError {\n constructor(\n adapter: string,\n public readonly retryAfter?: number,\n ) {\n super(\n `Rate limited by ${adapter}${retryAfter ? `, retry after ${retryAfter}s` : \"\"}`,\n adapter,\n \"RATE_LIMITED\",\n );\n this.name = \"AdapterRateLimitError\";\n }\n}\n\n/**\n * Authentication error - thrown when credentials are invalid or expired.\n *\n * @example\n * ```typescript\n * throw new AuthenticationError(\"teams\", \"Token expired\");\n * ```\n */\nexport class AuthenticationError extends AdapterError {\n constructor(adapter: string, message?: string) {\n super(\n message || `Authentication failed for ${adapter}`,\n adapter,\n \"AUTH_FAILED\",\n );\n this.name = \"AuthenticationError\";\n }\n}\n\n/**\n * Not found error - thrown when a requested resource doesn't exist.\n *\n * @example\n * ```typescript\n * throw new ResourceNotFoundError(\"slack\", \"channel\", \"C123456\");\n * // message: \"channel 'C123456' not found in slack\"\n * ```\n */\nexport class ResourceNotFoundError extends AdapterError {\n constructor(\n adapter: string,\n public readonly resourceType: string,\n public readonly resourceId?: string,\n ) {\n const idPart = resourceId ? ` '${resourceId}'` : \"\";\n super(\n `${resourceType}${idPart} not found in ${adapter}`,\n adapter,\n \"NOT_FOUND\",\n );\n this.name = \"ResourceNotFoundError\";\n }\n}\n\n/**\n * Permission error - thrown when the bot lacks required permissions.\n *\n * @example\n * ```typescript\n * throw new PermissionError(\"teams\", \"send messages\", \"channels:write\");\n * ```\n */\nexport class PermissionError extends AdapterError {\n constructor(\n adapter: string,\n public readonly action: string,\n public readonly requiredScope?: string,\n ) {\n const scopePart = requiredScope ? ` (requires: ${requiredScope})` : \"\";\n super(\n `Permission denied: cannot ${action} in ${adapter}${scopePart}`,\n adapter,\n \"PERMISSION_DENIED\",\n );\n this.name = \"PermissionError\";\n }\n}\n\n/**\n * Validation error - thrown when input data is invalid.\n *\n * @example\n * ```typescript\n * throw new ValidationError(\"slack\", \"Message text exceeds 40000 characters\");\n * ```\n */\nexport class ValidationError extends AdapterError {\n constructor(adapter: string, message: string) {\n super(message, adapter, \"VALIDATION_ERROR\");\n this.name = \"ValidationError\";\n }\n}\n\n/**\n * Network error - thrown when there's a network/connectivity issue.\n *\n * @example\n * ```typescript\n * throw new NetworkError(\"gchat\", \"Connection timeout after 30s\");\n * ```\n */\nexport class NetworkError extends AdapterError {\n constructor(\n adapter: string,\n message?: string,\n public readonly originalError?: Error,\n ) {\n super(\n message || `Network error communicating with ${adapter}`,\n adapter,\n \"NETWORK_ERROR\",\n );\n this.name = \"NetworkError\";\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/adapter-utils.ts","../src/errors.ts","../src/buffer-utils.ts","../src/card-utils.ts"],"sourcesContent":["/**\n * Shared utility functions for chat adapters.\n *\n * These utilities are used across all adapter implementations (Slack, Teams, GChat)\n * to reduce code duplication and ensure consistent behavior.\n */\n\nimport type { AdapterPostableMessage, CardElement, FileUpload } from \"chat\";\nimport { isCardElement } from \"chat\";\n\n/**\n * Extract CardElement from an AdapterPostableMessage if present.\n *\n * Handles two cases:\n * 1. The message IS a CardElement (type: \"card\")\n * 2. The message is a PostableCard with a `card` property\n *\n * @param message - The message to extract the card from\n * @returns The CardElement if found, null otherwise\n *\n * @example\n * ```typescript\n * // Case 1: Direct CardElement\n * const card = Card({ title: \"Test\" });\n * extractCard(card); // returns the card\n *\n * // Case 2: PostableCard wrapper\n * const message = { card, fallbackText: \"...\" };\n * extractCard(message); // returns the card\n *\n * // Case 3: Non-card message\n * extractCard(\"Hello\"); // returns null\n * extractCard({ markdown: \"**bold**\" }); // returns null\n * ```\n */\nexport function extractCard(\n message: AdapterPostableMessage,\n): CardElement | null {\n if (isCardElement(message)) {\n return message;\n }\n if (typeof message === \"object\" && message !== null && \"card\" in message) {\n return message.card;\n }\n return null;\n}\n\n/**\n * Extract FileUpload array from an AdapterPostableMessage if present.\n *\n * Files can be attached to PostableRaw, PostableMarkdown, PostableAst,\n * or PostableCard messages via the `files` property.\n *\n * @param message - The message to extract files from\n * @returns Array of FileUpload objects, or empty array if none\n *\n * @example\n * ```typescript\n * // With files\n * const message = {\n * markdown: \"**Text**\",\n * files: [{ data: Buffer.from(\"...\"), filename: \"doc.pdf\" }]\n * };\n * extractFiles(message); // returns the files array\n *\n * // Without files\n * extractFiles(\"Hello\"); // returns []\n * extractFiles({ raw: \"text\" }); // returns []\n * ```\n */\nexport function extractFiles(message: AdapterPostableMessage): FileUpload[] {\n if (typeof message === \"object\" && message !== null && \"files\" in message) {\n return (message as { files?: FileUpload[] }).files ?? [];\n }\n return [];\n}\n","/**\n * Standardized error types for chat adapters.\n *\n * These error classes provide consistent error handling across all\n * adapter implementations.\n */\n\n/**\n * Base error class for adapter operations.\n *\n * All adapter-specific errors should extend this class.\n */\nexport class AdapterError extends Error {\n /**\n * @param message - Human-readable error message\n * @param adapter - Name of the adapter (e.g., \"slack\", \"teams\", \"gchat\")\n * @param code - Optional error code for programmatic handling\n */\n constructor(\n message: string,\n public readonly adapter: string,\n public readonly code?: string,\n ) {\n super(message);\n this.name = \"AdapterError\";\n }\n}\n\n/**\n * Rate limit error - thrown when platform API rate limits are hit.\n *\n * @example\n * ```typescript\n * throw new AdapterRateLimitError(\"slack\", 30);\n * // message: \"Rate limited by slack, retry after 30s\"\n * ```\n */\nexport class AdapterRateLimitError extends AdapterError {\n constructor(\n adapter: string,\n public readonly retryAfter?: number,\n ) {\n super(\n `Rate limited by ${adapter}${retryAfter ? `, retry after ${retryAfter}s` : \"\"}`,\n adapter,\n \"RATE_LIMITED\",\n );\n this.name = \"AdapterRateLimitError\";\n }\n}\n\n/**\n * Authentication error - thrown when credentials are invalid or expired.\n *\n * @example\n * ```typescript\n * throw new AuthenticationError(\"teams\", \"Token expired\");\n * ```\n */\nexport class AuthenticationError extends AdapterError {\n constructor(adapter: string, message?: string) {\n super(\n message || `Authentication failed for ${adapter}`,\n adapter,\n \"AUTH_FAILED\",\n );\n this.name = \"AuthenticationError\";\n }\n}\n\n/**\n * Not found error - thrown when a requested resource doesn't exist.\n *\n * @example\n * ```typescript\n * throw new ResourceNotFoundError(\"slack\", \"channel\", \"C123456\");\n * // message: \"channel 'C123456' not found in slack\"\n * ```\n */\nexport class ResourceNotFoundError extends AdapterError {\n constructor(\n adapter: string,\n public readonly resourceType: string,\n public readonly resourceId?: string,\n ) {\n const idPart = resourceId ? ` '${resourceId}'` : \"\";\n super(\n `${resourceType}${idPart} not found in ${adapter}`,\n adapter,\n \"NOT_FOUND\",\n );\n this.name = \"ResourceNotFoundError\";\n }\n}\n\n/**\n * Permission error - thrown when the bot lacks required permissions.\n *\n * @example\n * ```typescript\n * throw new PermissionError(\"teams\", \"send messages\", \"channels:write\");\n * ```\n */\nexport class PermissionError extends AdapterError {\n constructor(\n adapter: string,\n public readonly action: string,\n public readonly requiredScope?: string,\n ) {\n const scopePart = requiredScope ? ` (requires: ${requiredScope})` : \"\";\n super(\n `Permission denied: cannot ${action} in ${adapter}${scopePart}`,\n adapter,\n \"PERMISSION_DENIED\",\n );\n this.name = \"PermissionError\";\n }\n}\n\n/**\n * Validation error - thrown when input data is invalid.\n *\n * @example\n * ```typescript\n * throw new ValidationError(\"slack\", \"Message text exceeds 40000 characters\");\n * ```\n */\nexport class ValidationError extends AdapterError {\n constructor(adapter: string, message: string) {\n super(message, adapter, \"VALIDATION_ERROR\");\n this.name = \"ValidationError\";\n }\n}\n\n/**\n * Network error - thrown when there's a network/connectivity issue.\n *\n * @example\n * ```typescript\n * throw new NetworkError(\"gchat\", \"Connection timeout after 30s\");\n * ```\n */\nexport class NetworkError extends AdapterError {\n constructor(\n adapter: string,\n message?: string,\n public readonly originalError?: Error,\n ) {\n super(\n message || `Network error communicating with ${adapter}`,\n adapter,\n \"NETWORK_ERROR\",\n );\n this.name = \"NetworkError\";\n }\n}\n","/**\n * Buffer conversion utilities for handling file uploads.\n *\n * These utilities handle the conversion of various data types\n * (Buffer, ArrayBuffer, Blob) to Node.js Buffer for file uploads.\n */\n\nimport type { PlatformName } from \"./card-utils\";\nimport { ValidationError } from \"./errors\";\n\n/**\n * The supported input types for file data.\n */\nexport type FileDataInput = Buffer | ArrayBuffer | Blob;\n\n/**\n * Options for buffer conversion.\n */\nexport interface ToBufferOptions {\n /**\n * The platform name for error messages.\n */\n platform: PlatformName;\n\n /**\n * If true, throws ValidationError for unsupported types.\n * If false, returns null for unsupported types.\n * Default: true\n */\n throwOnUnsupported?: boolean;\n}\n\n/**\n * Convert various data types to a Node.js Buffer.\n *\n * Handles:\n * - Buffer: returned as-is\n * - ArrayBuffer: converted using Buffer.from()\n * - Blob: converted via arrayBuffer() then Buffer.from()\n *\n * @param data - The file data to convert\n * @param options - Conversion options\n * @returns Buffer or null if conversion fails and throwOnUnsupported is false\n * @throws ValidationError if data type is unsupported and throwOnUnsupported is true\n *\n * @example\n * ```typescript\n * // Throw on unsupported (default behavior)\n * const buffer = await toBuffer(file.data, { platform: \"slack\" });\n *\n * // Return null on unsupported\n * const buffer = await toBuffer(file.data, { platform: \"teams\", throwOnUnsupported: false });\n * if (!buffer) continue; // Skip unsupported files\n * ```\n */\nexport async function toBuffer(\n data: FileDataInput | unknown,\n options: ToBufferOptions,\n): Promise<Buffer | null> {\n const { platform, throwOnUnsupported = true } = options;\n\n if (Buffer.isBuffer(data)) {\n return data;\n }\n\n if (data instanceof ArrayBuffer) {\n return Buffer.from(data);\n }\n\n if (data instanceof Blob) {\n const arrayBuffer = await data.arrayBuffer();\n return Buffer.from(arrayBuffer);\n }\n\n if (throwOnUnsupported) {\n throw new ValidationError(platform, \"Unsupported file data type\");\n }\n\n return null;\n}\n\n/**\n * Synchronous version of toBuffer for non-Blob data.\n *\n * Use this when you know the data is not a Blob (e.g., already validated).\n *\n * @param data - The file data to convert (Buffer or ArrayBuffer only)\n * @param options - Conversion options\n * @returns Buffer or null if conversion fails\n * @throws ValidationError if data is a Blob or unsupported type and throwOnUnsupported is true\n */\nexport function toBufferSync(\n data: Buffer | ArrayBuffer | unknown,\n options: ToBufferOptions,\n): Buffer | null {\n const { platform, throwOnUnsupported = true } = options;\n\n if (Buffer.isBuffer(data)) {\n return data;\n }\n\n if (data instanceof ArrayBuffer) {\n return Buffer.from(data);\n }\n\n if (data instanceof Blob) {\n if (throwOnUnsupported) {\n throw new ValidationError(\n platform,\n \"Cannot convert Blob synchronously. Use toBuffer() for async conversion.\",\n );\n }\n return null;\n }\n\n if (throwOnUnsupported) {\n throw new ValidationError(platform, \"Unsupported file data type\");\n }\n\n return null;\n}\n\n/**\n * Convert a Buffer to a data URI string.\n *\n * @param buffer - The buffer to convert\n * @param mimeType - The MIME type (default: application/octet-stream)\n * @returns Data URI string in format `data:{mimeType};base64,{base64Data}`\n *\n * @example\n * ```typescript\n * const dataUri = bufferToDataUri(buffer, \"image/png\");\n * // \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgA...\"\n * ```\n */\nexport function bufferToDataUri(\n buffer: Buffer,\n mimeType = \"application/octet-stream\",\n): string {\n const base64 = buffer.toString(\"base64\");\n return `data:${mimeType};base64,${base64}`;\n}\n","/**\n * Shared card conversion utilities for adapters.\n *\n * These utilities reduce duplication across adapter implementations\n * for card-to-platform-format conversions.\n */\n\nimport type { ButtonElement, CardChild, CardElement } from \"chat\";\nimport { convertEmojiPlaceholders } from \"chat\";\n\n/**\n * Supported platform names for adapter utilities.\n */\nexport type PlatformName = \"slack\" | \"gchat\" | \"teams\" | \"discord\";\n\n/**\n * Button style mappings per platform.\n *\n * Maps our standard button styles (\"primary\", \"danger\") to\n * platform-specific values.\n */\nexport const BUTTON_STYLE_MAPPINGS: Record<\n PlatformName,\n Record<string, string>\n> = {\n slack: { primary: \"primary\", danger: \"danger\" },\n gchat: { primary: \"primary\", danger: \"danger\" }, // Colors handled via buttonColor\n teams: { primary: \"positive\", danger: \"destructive\" },\n discord: { primary: \"primary\", danger: \"danger\" },\n};\n\n/**\n * Create a platform-specific emoji converter function.\n *\n * Returns a function that converts emoji placeholders (e.g., `{{emoji:wave}}`)\n * to the platform's native format.\n *\n * @example\n * ```typescript\n * const convertEmoji = createEmojiConverter(\"slack\");\n * convertEmoji(\"{{emoji:wave}} Hello\"); // \":wave: Hello\"\n * ```\n */\nexport function createEmojiConverter(\n platform: PlatformName,\n): (text: string) => string {\n return (text: string) => convertEmojiPlaceholders(text, platform);\n}\n\n/**\n * Map a button style to the platform-specific value.\n *\n * @example\n * ```typescript\n * mapButtonStyle(\"primary\", \"teams\"); // \"positive\"\n * mapButtonStyle(\"danger\", \"slack\"); // \"danger\"\n * mapButtonStyle(undefined, \"teams\"); // undefined\n * ```\n */\nexport function mapButtonStyle(\n style: ButtonElement[\"style\"],\n platform: PlatformName,\n): string | undefined {\n if (!style) return undefined;\n return BUTTON_STYLE_MAPPINGS[platform][style];\n}\n\n/**\n * Options for fallback text generation.\n */\nexport interface FallbackTextOptions {\n /** Bold format string (default: \"*\" for mrkdwn, \"**\" for markdown) */\n boldFormat?: \"*\" | \"**\";\n /** Line break between sections (default: \"\\n\") */\n lineBreak?: \"\\n\" | \"\\n\\n\";\n /** Platform for emoji conversion (optional) */\n platform?: PlatformName;\n}\n\n/**\n * Generate fallback plain text from a card element.\n *\n * Used when the platform can't render rich cards or for notification previews.\n * Consolidates duplicate implementations from individual adapters.\n *\n * @example\n * ```typescript\n * // Slack-style (mrkdwn)\n * cardToFallbackText(card, { boldFormat: \"*\", platform: \"slack\" });\n *\n * // Teams-style (markdown with double line breaks)\n * cardToFallbackText(card, { boldFormat: \"**\", lineBreak: \"\\n\\n\", platform: \"teams\" });\n * ```\n */\nexport function cardToFallbackText(\n card: CardElement,\n options: FallbackTextOptions = {},\n): string {\n const { boldFormat = \"*\", lineBreak = \"\\n\", platform } = options;\n\n const convertText = platform\n ? createEmojiConverter(platform)\n : (t: string) => t;\n\n const parts: string[] = [];\n\n if (card.title) {\n parts.push(`${boldFormat}${convertText(card.title)}${boldFormat}`);\n }\n\n if (card.subtitle) {\n parts.push(convertText(card.subtitle));\n }\n\n for (const child of card.children) {\n const text = childToFallbackText(child, convertText);\n if (text) {\n parts.push(text);\n }\n }\n\n return parts.join(lineBreak);\n}\n\n/**\n * Convert a card child element to fallback text.\n * Internal helper for cardToFallbackText.\n */\nfunction childToFallbackText(\n child: CardChild,\n convertText: (t: string) => string,\n): string | null {\n switch (child.type) {\n case \"text\":\n return convertText(child.content);\n case \"fields\":\n return child.children\n .map((f) => `${convertText(f.label)}: ${convertText(f.value)}`)\n .join(\"\\n\");\n case \"actions\":\n return `[${child.children.map((b) => convertText(b.label)).join(\"] [\")}]`;\n case \"section\":\n return child.children\n .map((c) => childToFallbackText(c, convertText))\n .filter(Boolean)\n .join(\"\\n\");\n case \"divider\":\n return \"---\";\n default:\n return null;\n }\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chat-adapter/shared",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.4.0",
|
|
4
4
|
"description": "Shared utilities for chat SDK adapters",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -15,10 +15,10 @@
|
|
|
15
15
|
"dist"
|
|
16
16
|
],
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"chat": "4.
|
|
18
|
+
"chat": "4.4.0"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
|
-
"@biomejs/biome": "^
|
|
21
|
+
"@biomejs/biome": "^2.3.10",
|
|
22
22
|
"@types/node": "^22.10.2",
|
|
23
23
|
"tsup": "^8.3.5",
|
|
24
24
|
"typescript": "^5.7.2",
|