@blockspark/chat-widget 1.0.8 → 1.0.10
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 +117 -123
- package/dist/ChatWidget-DFIQ9wIN.js +2 -0
- package/dist/ChatWidget-DFIQ9wIN.js.map +1 -0
- package/dist/{core/stateManager.esm.js → ChatWidget-DqEGRWH3.mjs} +450 -4
- package/dist/ChatWidget-DqEGRWH3.mjs.map +1 -0
- package/dist/index.cjs.js +1 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +1338 -7
- package/dist/index.esm.js.map +1 -1
- package/dist/nuxt.cjs.js +1 -1
- package/dist/nuxt.esm.js +4 -5
- package/dist/nuxt.esm.js.map +1 -1
- package/dist/sanitize-7Fj9oshH.js +3 -0
- package/dist/sanitize-7Fj9oshH.js.map +1 -0
- package/dist/sanitize-BNRb-K3t.mjs +2847 -0
- package/dist/sanitize-BNRb-K3t.mjs.map +1 -0
- package/dist/utils/frameworkDetector.d.ts.map +1 -1
- package/dist/utils/sanitize.d.ts.map +1 -1
- package/dist/vue.cjs.js +1 -1
- package/dist/vue.esm.js +4 -5
- package/dist/vue.esm.js.map +1 -1
- package/package.json +1 -1
- package/dist/_virtual/_plugin-vue_export-helper.cjs.js +0 -2
- package/dist/_virtual/_plugin-vue_export-helper.cjs.js.map +0 -1
- package/dist/_virtual/_plugin-vue_export-helper.esm.js +0 -11
- package/dist/_virtual/_plugin-vue_export-helper.esm.js.map +0 -1
- package/dist/components/ChatWidget.cjs.js +0 -2
- package/dist/components/ChatWidget.cjs.js.map +0 -1
- package/dist/components/ChatWidget.esm.js +0 -1129
- package/dist/components/ChatWidget.esm.js.map +0 -1
- package/dist/components/ChatWidget.vue.cjs.js +0 -2
- package/dist/components/ChatWidget.vue.cjs.js.map +0 -1
- package/dist/components/ChatWidget.vue.cjs2.js +0 -2
- package/dist/components/ChatWidget.vue.cjs2.js.map +0 -1
- package/dist/components/ChatWidget.vue.esm.js +0 -8
- package/dist/components/ChatWidget.vue.esm.js.map +0 -1
- package/dist/components/ChatWidget.vue.esm2.js +0 -374
- package/dist/components/ChatWidget.vue.esm2.js.map +0 -1
- package/dist/composables/useChatWidget.cjs.js +0 -2
- package/dist/composables/useChatWidget.cjs.js.map +0 -1
- package/dist/composables/useChatWidget.esm.js +0 -75
- package/dist/composables/useChatWidget.esm.js.map +0 -1
- package/dist/core/stateManager.cjs.js +0 -2
- package/dist/core/stateManager.cjs.js.map +0 -1
- package/dist/core/stateManager.esm.js.map +0 -1
- package/dist/entry/vanilla.cjs.js +0 -2
- package/dist/entry/vanilla.cjs.js.map +0 -1
- package/dist/entry/vanilla.esm.js +0 -50
- package/dist/entry/vanilla.esm.js.map +0 -1
- package/dist/hooks/useChatMode.cjs.js +0 -2
- package/dist/hooks/useChatMode.cjs.js.map +0 -1
- package/dist/hooks/useChatMode.esm.js +0 -61
- package/dist/hooks/useChatMode.esm.js.map +0 -1
- package/dist/node_modules/jose/dist/browser/jws/compact/sign.cjs.js +0 -2
- package/dist/node_modules/jose/dist/browser/jws/compact/sign.cjs.js.map +0 -1
- package/dist/node_modules/jose/dist/browser/jws/compact/sign.esm.js +0 -21
- package/dist/node_modules/jose/dist/browser/jws/compact/sign.esm.js.map +0 -1
- package/dist/node_modules/jose/dist/browser/jws/flattened/sign.cjs.js +0 -2
- package/dist/node_modules/jose/dist/browser/jws/flattened/sign.cjs.js.map +0 -1
- package/dist/node_modules/jose/dist/browser/jws/flattened/sign.esm.js +0 -84
- package/dist/node_modules/jose/dist/browser/jws/flattened/sign.esm.js.map +0 -1
- package/dist/node_modules/jose/dist/browser/jwt/produce.cjs.js +0 -2
- package/dist/node_modules/jose/dist/browser/jwt/produce.cjs.js.map +0 -1
- package/dist/node_modules/jose/dist/browser/jwt/produce.esm.js +0 -72
- package/dist/node_modules/jose/dist/browser/jwt/produce.esm.js.map +0 -1
- package/dist/node_modules/jose/dist/browser/jwt/sign.cjs.js +0 -2
- package/dist/node_modules/jose/dist/browser/jwt/sign.cjs.js.map +0 -1
- package/dist/node_modules/jose/dist/browser/jwt/sign.esm.js +0 -22
- package/dist/node_modules/jose/dist/browser/jwt/sign.esm.js.map +0 -1
- package/dist/node_modules/jose/dist/browser/key/import.cjs.js +0 -2
- package/dist/node_modules/jose/dist/browser/key/import.cjs.js.map +0 -1
- package/dist/node_modules/jose/dist/browser/key/import.esm.js +0 -11
- package/dist/node_modules/jose/dist/browser/key/import.esm.js.map +0 -1
- package/dist/node_modules/jose/dist/browser/lib/buffer_utils.cjs.js +0 -2
- package/dist/node_modules/jose/dist/browser/lib/buffer_utils.cjs.js.map +0 -1
- package/dist/node_modules/jose/dist/browser/lib/buffer_utils.esm.js +0 -18
- package/dist/node_modules/jose/dist/browser/lib/buffer_utils.esm.js.map +0 -1
- package/dist/node_modules/jose/dist/browser/lib/check_key_type.cjs.js +0 -2
- package/dist/node_modules/jose/dist/browser/lib/check_key_type.cjs.js.map +0 -1
- package/dist/node_modules/jose/dist/browser/lib/check_key_type.esm.js +0 -77
- package/dist/node_modules/jose/dist/browser/lib/check_key_type.esm.js.map +0 -1
- package/dist/node_modules/jose/dist/browser/lib/crypto_key.cjs.js +0 -2
- package/dist/node_modules/jose/dist/browser/lib/crypto_key.cjs.js.map +0 -1
- package/dist/node_modules/jose/dist/browser/lib/crypto_key.esm.js +0 -101
- package/dist/node_modules/jose/dist/browser/lib/crypto_key.esm.js.map +0 -1
- package/dist/node_modules/jose/dist/browser/lib/epoch.cjs.js +0 -2
- package/dist/node_modules/jose/dist/browser/lib/epoch.cjs.js.map +0 -1
- package/dist/node_modules/jose/dist/browser/lib/epoch.esm.js +0 -5
- package/dist/node_modules/jose/dist/browser/lib/epoch.esm.js.map +0 -1
- package/dist/node_modules/jose/dist/browser/lib/invalid_key_input.cjs.js +0 -2
- package/dist/node_modules/jose/dist/browser/lib/invalid_key_input.cjs.js.map +0 -1
- package/dist/node_modules/jose/dist/browser/lib/invalid_key_input.esm.js +0 -32
- package/dist/node_modules/jose/dist/browser/lib/invalid_key_input.esm.js.map +0 -1
- package/dist/node_modules/jose/dist/browser/lib/is_disjoint.cjs.js +0 -2
- package/dist/node_modules/jose/dist/browser/lib/is_disjoint.cjs.js.map +0 -1
- package/dist/node_modules/jose/dist/browser/lib/is_disjoint.esm.js +0 -25
- package/dist/node_modules/jose/dist/browser/lib/is_disjoint.esm.js.map +0 -1
- package/dist/node_modules/jose/dist/browser/lib/is_jwk.cjs.js +0 -2
- package/dist/node_modules/jose/dist/browser/lib/is_jwk.cjs.js.map +0 -1
- package/dist/node_modules/jose/dist/browser/lib/is_jwk.esm.js +0 -20
- package/dist/node_modules/jose/dist/browser/lib/is_jwk.esm.js.map +0 -1
- package/dist/node_modules/jose/dist/browser/lib/is_object.cjs.js +0 -2
- package/dist/node_modules/jose/dist/browser/lib/is_object.cjs.js.map +0 -1
- package/dist/node_modules/jose/dist/browser/lib/is_object.esm.js +0 -20
- package/dist/node_modules/jose/dist/browser/lib/is_object.esm.js.map +0 -1
- package/dist/node_modules/jose/dist/browser/lib/secs.cjs.js +0 -2
- package/dist/node_modules/jose/dist/browser/lib/secs.cjs.js.map +0 -1
- package/dist/node_modules/jose/dist/browser/lib/secs.esm.js +0 -59
- package/dist/node_modules/jose/dist/browser/lib/secs.esm.js.map +0 -1
- package/dist/node_modules/jose/dist/browser/lib/validate_crit.cjs.js +0 -2
- package/dist/node_modules/jose/dist/browser/lib/validate_crit.cjs.js.map +0 -1
- package/dist/node_modules/jose/dist/browser/lib/validate_crit.esm.js +0 -34
- package/dist/node_modules/jose/dist/browser/lib/validate_crit.esm.js.map +0 -1
- package/dist/node_modules/jose/dist/browser/runtime/asn1.cjs.js +0 -2
- package/dist/node_modules/jose/dist/browser/runtime/asn1.cjs.js.map +0 -1
- package/dist/node_modules/jose/dist/browser/runtime/asn1.esm.js +0 -103
- package/dist/node_modules/jose/dist/browser/runtime/asn1.esm.js.map +0 -1
- package/dist/node_modules/jose/dist/browser/runtime/base64url.cjs.js +0 -2
- package/dist/node_modules/jose/dist/browser/runtime/base64url.cjs.js.map +0 -1
- package/dist/node_modules/jose/dist/browser/runtime/base64url.esm.js +0 -43
- package/dist/node_modules/jose/dist/browser/runtime/base64url.esm.js.map +0 -1
- package/dist/node_modules/jose/dist/browser/runtime/check_key_length.cjs.js +0 -2
- package/dist/node_modules/jose/dist/browser/runtime/check_key_length.cjs.js.map +0 -1
- package/dist/node_modules/jose/dist/browser/runtime/check_key_length.esm.js +0 -12
- package/dist/node_modules/jose/dist/browser/runtime/check_key_length.esm.js.map +0 -1
- package/dist/node_modules/jose/dist/browser/runtime/get_sign_verify_key.cjs.js +0 -2
- package/dist/node_modules/jose/dist/browser/runtime/get_sign_verify_key.cjs.js.map +0 -1
- package/dist/node_modules/jose/dist/browser/runtime/get_sign_verify_key.esm.js +0 -25
- package/dist/node_modules/jose/dist/browser/runtime/get_sign_verify_key.esm.js.map +0 -1
- package/dist/node_modules/jose/dist/browser/runtime/is_key_like.cjs.js +0 -2
- package/dist/node_modules/jose/dist/browser/runtime/is_key_like.cjs.js.map +0 -1
- package/dist/node_modules/jose/dist/browser/runtime/is_key_like.esm.js +0 -13
- package/dist/node_modules/jose/dist/browser/runtime/is_key_like.esm.js.map +0 -1
- package/dist/node_modules/jose/dist/browser/runtime/jwk_to_key.cjs.js +0 -2
- package/dist/node_modules/jose/dist/browser/runtime/jwk_to_key.cjs.js.map +0 -1
- package/dist/node_modules/jose/dist/browser/runtime/jwk_to_key.esm.js +0 -107
- package/dist/node_modules/jose/dist/browser/runtime/jwk_to_key.esm.js.map +0 -1
- package/dist/node_modules/jose/dist/browser/runtime/normalize_key.cjs.js +0 -2
- package/dist/node_modules/jose/dist/browser/runtime/normalize_key.cjs.js.map +0 -1
- package/dist/node_modules/jose/dist/browser/runtime/normalize_key.esm.js +0 -71
- package/dist/node_modules/jose/dist/browser/runtime/normalize_key.esm.js.map +0 -1
- package/dist/node_modules/jose/dist/browser/runtime/sign.cjs.js +0 -2
- package/dist/node_modules/jose/dist/browser/runtime/sign.cjs.js.map +0 -1
- package/dist/node_modules/jose/dist/browser/runtime/sign.esm.js +0 -14
- package/dist/node_modules/jose/dist/browser/runtime/sign.esm.js.map +0 -1
- package/dist/node_modules/jose/dist/browser/runtime/subtle_dsa.cjs.js +0 -2
- package/dist/node_modules/jose/dist/browser/runtime/subtle_dsa.cjs.js.map +0 -1
- package/dist/node_modules/jose/dist/browser/runtime/subtle_dsa.esm.js +0 -32
- package/dist/node_modules/jose/dist/browser/runtime/subtle_dsa.esm.js.map +0 -1
- package/dist/node_modules/jose/dist/browser/runtime/webcrypto.cjs.js +0 -2
- package/dist/node_modules/jose/dist/browser/runtime/webcrypto.cjs.js.map +0 -1
- package/dist/node_modules/jose/dist/browser/runtime/webcrypto.esm.js +0 -7
- package/dist/node_modules/jose/dist/browser/runtime/webcrypto.esm.js.map +0 -1
- package/dist/node_modules/jose/dist/browser/util/errors.cjs.js +0 -2
- package/dist/node_modules/jose/dist/browser/util/errors.cjs.js.map +0 -1
- package/dist/node_modules/jose/dist/browser/util/errors.esm.js +0 -131
- package/dist/node_modules/jose/dist/browser/util/errors.esm.js.map +0 -1
- package/dist/node_modules/react-dom/client.cjs.js +0 -2
- package/dist/node_modules/react-dom/client.cjs.js.map +0 -1
- package/dist/node_modules/react-dom/client.esm.js +0 -21
- package/dist/node_modules/react-dom/client.esm.js.map +0 -1
- package/dist/services/chatService.cjs.js +0 -2
- package/dist/services/chatService.cjs.js.map +0 -1
- package/dist/services/chatService.esm.js +0 -482
- package/dist/services/chatService.esm.js.map +0 -1
- package/dist/services/dialogflowClient.cjs.js +0 -2
- package/dist/services/dialogflowClient.cjs.js.map +0 -1
- package/dist/services/dialogflowClient.esm.js +0 -282
- package/dist/services/dialogflowClient.esm.js.map +0 -1
- package/dist/services/sessionManager.cjs.js +0 -2
- package/dist/services/sessionManager.cjs.js.map +0 -1
- package/dist/services/sessionManager.esm.js +0 -48
- package/dist/services/sessionManager.esm.js.map +0 -1
- package/dist/utils/frameworkDetector.cjs.js +0 -2
- package/dist/utils/frameworkDetector.cjs.js.map +0 -1
- package/dist/utils/frameworkDetector.esm.js +0 -125
- package/dist/utils/frameworkDetector.esm.js.map +0 -1
- package/dist/utils/sanitize.cjs.js +0 -2
- package/dist/utils/sanitize.cjs.js.map +0 -1
- package/dist/utils/sanitize.esm.js +0 -52
- package/dist/utils/sanitize.esm.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"dialogflowClient.cjs.js","sources":["../../src/services/dialogflowClient.ts"],"sourcesContent":["// services/dialogflowClient.ts\nimport { SignJWT, importPKCS8 } from 'jose';\n// dotenv removed - environment variables should be handled by the consuming application\n\n\nexport interface DialogflowConfig {\n dfProjectId: string;\n dfLocation: string;\n dfAgentId: string;\n serviceAccountKey?: any; // Service account JSON object\n accessToken?: string; // Alternative: provide access token directly\n languageCode?: string;\n}\n\nexport interface SessionResponse {\n session_id: string;\n message: string;\n richContent?: any;\n}\n\nexport interface ChatResponse {\n response: string;\n session_id: string;\n source: string;\n timestamp: string;\n richContent?: any;\n handoff?: boolean;\n}\n\n// Helper to get access token from service account using Web Crypto API\nasync function getAccessTokenFromServiceAccount(serviceAccountKey: any): Promise<string> {\n const now = Math.floor(Date.now() / 1000);\n \n // Format the private key - ensure it's properly formatted for PKCS#8\n let privateKeyPem = serviceAccountKey.private_key;\n \n // Google service account keys should already be in PKCS#8 format\n // But we need to ensure proper formatting with newlines\n if (privateKeyPem) {\n // Remove any existing whitespace/newlines\n privateKeyPem = privateKeyPem.trim();\n \n // If it doesn't have headers, it's just the base64 content\n if (!privateKeyPem.includes('-----BEGIN')) {\n // Wrap the base64 content with proper headers\n // Split into 64-character lines for proper PEM format\n const keyContent = privateKeyPem.replace(/\\s/g, '');\n const formattedKey = keyContent.match(/.{1,64}/g)?.join('\\n') || keyContent;\n privateKeyPem = `-----BEGIN PRIVATE KEY-----\\n${formattedKey}\\n-----END PRIVATE KEY-----`;\n } else {\n // Key has headers, but ensure proper line breaks\n // Normalize line breaks to \\n\n privateKeyPem = privateKeyPem.replace(/\\r\\n/g, '\\n').replace(/\\r/g, '\\n');\n \n // If it's RSA PRIVATE KEY (PKCS#1), we need to note that jose can't convert it\n // Google service accounts should provide PKCS#8, but if not, we'll try to use as-is\n if (privateKeyPem.includes('BEGIN RSA PRIVATE KEY')) {\n throw new Error(\n 'Private key is in PKCS#1 format (RSA PRIVATE KEY). ' +\n 'Please download a new service account key from Google Cloud Console. ' +\n 'The key should be in PKCS#8 format (PRIVATE KEY).'\n );\n }\n \n // Ensure the key content is properly formatted (64 chars per line)\n const keyMatch = privateKeyPem.match(/-----BEGIN PRIVATE KEY-----\\n?([\\s\\S]*?)\\n?-----END PRIVATE KEY-----/);\n if (keyMatch) {\n const keyContent = keyMatch[1].replace(/\\s/g, '');\n // Check if already properly formatted (has newlines every 64 chars)\n if (!keyContent.includes('\\n') || keyContent.length > 64) {\n const formattedKey = keyContent.match(/.{1,64}/g)?.join('\\n') || keyContent;\n privateKeyPem = `-----BEGIN PRIVATE KEY-----\\n${formattedKey}\\n-----END PRIVATE KEY-----`;\n }\n }\n }\n } else {\n throw new Error('Private key is missing from service account key');\n }\n \n try {\n // Import the private key (jose expects PKCS#8 format)\n const privateKey = await importPKCS8(privateKeyPem, 'RS256');\n \n // Create JWT\n const jwt = await new SignJWT({\n scope: 'https://www.googleapis.com/auth/cloud-platform',\n })\n .setProtectedHeader({ alg: 'RS256' })\n .setIssuedAt(now)\n .setExpirationTime(now + 3600)\n .setIssuer(serviceAccountKey.client_email)\n .setSubject(serviceAccountKey.client_email)\n .setAudience('https://oauth2.googleapis.com/token')\n .sign(privateKey);\n\n // Exchange JWT for access token\n const response = await fetch('https://oauth2.googleapis.com/token', {\n method: 'POST',\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n body: new URLSearchParams({\n grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',\n assertion: jwt,\n }),\n });\n\n if (!response.ok) {\n const error = await response.json();\n throw new Error(error.error_description || 'Failed to get access token');\n }\n\n const data = await response.json();\n return data.access_token;\n } catch (error: any) {\n if (error.message && error.message.includes('pkcs8')) {\n throw new Error(\n 'Invalid private key format. The service account key must be in PKCS#8 format. ' +\n 'Please ensure your service account key JSON file has a properly formatted private_key field. ' +\n 'If you downloaded the key from Google Cloud Console, it should already be in the correct format.'\n );\n }\n throw error;\n }\n}\n\n// Get access token (either from service account or use provided token)\nasync function getAccessToken(config: DialogflowConfig): Promise<string> {\n if (config.accessToken) {\n return config.accessToken;\n }\n \n if (!config.serviceAccountKey) {\n throw new Error('Either serviceAccountKey or accessToken must be provided');\n }\n\n return await getAccessTokenFromServiceAccount(config.serviceAccountKey);\n}\n\n// Create session path\nfunction createSessionPath(projectId: string, location: string, agentId: string, sessionId: string): string {\n return `projects/${projectId}/locations/${location}/agents/${agentId}/sessions/${sessionId}`;\n}\n\n// Extract rich content from Dialogflow response\nfunction extractRichContent(responseMessages: any[]): any {\n let richContent = null;\n \n for (const msg of responseMessages) {\n if (msg.payload) {\n if (msg.payload.richContent) {\n richContent = msg.payload.richContent;\n break;\n }\n if (msg.payload.fields && msg.payload.fields.richContent) {\n const richContentValue = msg.payload.fields.richContent;\n if (richContentValue.listValue && richContentValue.listValue.values) {\n richContent = richContentValue.listValue.values.map((v: any) => {\n if (v.listValue && v.listValue.values) {\n return v.listValue.values.map((item: any) => {\n if (item.structValue && item.structValue.fields) {\n const fields = item.structValue.fields;\n if (fields.type && fields.options) {\n return {\n type: fields.type.stringValue || fields.type,\n options: fields.options.listValue\n ? fields.options.listValue.values.map((opt: any) => ({\n text: opt.structValue?.fields?.text?.stringValue || '',\n payload: opt.structValue?.fields?.payload?.stringValue || '',\n }))\n : [],\n };\n }\n }\n return item;\n });\n }\n return v;\n });\n } else if (typeof richContentValue === 'object' && !richContentValue.listValue) {\n richContent = richContentValue;\n }\n break;\n }\n }\n }\n \n return richContent;\n}\n\n/**\n * Create a new Dialogflow session\n * @param config - Dialogflow configuration\n * @returns Promise with session ID and welcome message\n */\nexport async function createDialogflowSession(config: DialogflowConfig): Promise<SessionResponse> {\n try {\n const accessToken = await getAccessToken(config);\n const sessionId = `session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n const location = config.dfLocation.split(' ')[0].trim(); // Extract just the location code\n const sessionPath = createSessionPath(\n config.dfProjectId,\n location,\n config.dfAgentId,\n sessionId\n );\n\n const apiEndpoint = `https://${location}-dialogflow.googleapis.com/v3/${sessionPath}:detectIntent`;\n\n // Get welcome message\n const request = {\n queryInput: {\n text: {\n text: 'hello',\n },\n languageCode: config.languageCode || 'en',\n },\n };\n\n const response = await fetch(apiEndpoint, {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${accessToken}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(request),\n });\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({}));\n throw new Error(error.error?.message || `HTTP error! status: ${response.status}`);\n }\n\n const data = await response.json();\n \n let welcomeMessage = \"Hello! I'm BlockSpark AI Assistant. How can I help you today?\";\n let richContent = null;\n\n if (data.queryResult?.responseMessages) {\n const textMessages = data.queryResult.responseMessages\n .filter((msg: any) => msg.text)\n .map((msg: any) => msg.text.text.join(' '));\n \n if (textMessages.length > 0) {\n welcomeMessage = textMessages.join(' ');\n }\n\n richContent = extractRichContent(data.queryResult.responseMessages);\n } else if (data.queryResult?.fulfillmentText) {\n welcomeMessage = data.queryResult.fulfillmentText;\n }\n\n return {\n session_id: sessionId,\n message: welcomeMessage,\n ...(richContent && { richContent }),\n };\n } catch (error: any) {\n console.error('Error creating Dialogflow session:', error);\n const errorMessage = error.message || 'Failed to create session';\n if (errorMessage.includes('401') || errorMessage.includes('Unauthorized')) {\n throw new Error('Authentication failed. Please check your service account key or access token.');\n } else if (errorMessage.includes('403') || errorMessage.includes('Forbidden')) {\n throw new Error('Access forbidden. Please check your Dialogflow API permissions.');\n } else if (errorMessage.includes('404') || errorMessage.includes('Not Found')) {\n throw new Error('Dialogflow agent not found. Please check your project ID, location, and agent ID.');\n }\n throw new Error(errorMessage);\n }\n}\n\n/**\n * Send a message to Dialogflow\n * @param message - The user's message\n * @param sessionId - The session ID\n * @param config - Dialogflow configuration\n * @returns Promise with bot response\n */\nexport async function sendDialogflowMessage(\n message: string,\n sessionId: string,\n config: DialogflowConfig\n): Promise<ChatResponse> {\n try {\n const accessToken = await getAccessToken(config);\n const location = config.dfLocation.split(' ')[0].trim(); // Extract just the location code\n const sessionPath = createSessionPath(\n config.dfProjectId,\n location,\n config.dfAgentId,\n sessionId\n );\n\n const apiEndpoint = `https://${location}-dialogflow.googleapis.com/v3/${sessionPath}:detectIntent`;\n\n const request = {\n queryInput: {\n text: {\n text: message.trim(),\n },\n languageCode: config.languageCode || 'en',\n },\n };\n\n const response = await fetch(apiEndpoint, {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${accessToken}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(request),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n let errorData: any = {};\n try {\n errorData = JSON.parse(errorText);\n } catch {\n errorData = { message: errorText || `HTTP ${response.status}` };\n }\n const errorMessage = errorData.error?.message || errorData.message || `HTTP error! status: ${response.status}`;\n console.error('Dialogflow API Error (sendMessage):', {\n status: response.status,\n statusText: response.statusText,\n error: errorData,\n endpoint: apiEndpoint,\n });\n throw new Error(errorMessage);\n }\n\n const data = await response.json();\n\n let responseText = \"I'm sorry, I didn't understand that. Could you please rephrase?\";\n let richContent = null;\n let handoff = false;\n\n // Check for handoff trigger\n if (data.queryResult?.parameters?.fields?.handoff?.boolValue === true) {\n handoff = true;\n } else if (data.queryResult?.responseMessages) {\n // Check in responseMessages payload\n for (const msg of data.queryResult.responseMessages) {\n if (msg.payload) {\n if (typeof msg.payload === 'object') {\n if (msg.payload.handoff === true) {\n handoff = true;\n break;\n }\n if (msg.payload.fields?.handoff?.boolValue === true) {\n handoff = true;\n break;\n }\n }\n }\n }\n }\n \n // Check at root level\n if (data.handoff === true) {\n handoff = true;\n }\n\n if (data.queryResult?.responseMessages) {\n const textMessages = data.queryResult.responseMessages\n .filter((msg: any) => msg.text)\n .map((msg: any) => msg.text.text.join(' '));\n \n if (textMessages.length > 0) {\n responseText = textMessages.join(' ');\n }\n\n richContent = extractRichContent(data.queryResult.responseMessages);\n } else if (data.queryResult?.fulfillmentText) {\n responseText = data.queryResult.fulfillmentText;\n }\n\n return {\n response: responseText,\n session_id: sessionId,\n source: 'dialogflow',\n timestamp: new Date().toISOString(),\n ...(richContent && { richContent }),\n ...(handoff && { handoff: true }),\n };\n } catch (error: any) {\n console.error('Error sending message to Dialogflow:', error);\n const errorMessage = error.message || 'Failed to send message';\n if (errorMessage.includes('401') || errorMessage.includes('Unauthorized')) {\n throw new Error('Authentication failed. Please check your service account key or access token.');\n } else if (errorMessage.includes('403') || errorMessage.includes('Forbidden')) {\n throw new Error('Access forbidden. Please check your Dialogflow API permissions.');\n } else if (errorMessage.includes('404') || errorMessage.includes('Not Found')) {\n throw new Error('Dialogflow agent not found. Please check your project ID, location, and agent ID.');\n } else if (errorMessage.includes('CORS')) {\n throw new Error('CORS error. Dialogflow API may not allow browser requests. Consider using a backend proxy.');\n }\n throw new Error(errorMessage);\n }\n}\n\n"],"names":["async","getAccessToken","config","accessToken","serviceAccountKey","Error","now","Math","floor","Date","privateKeyPem","private_key","trim","includes","replace","keyMatch","match","keyContent","length","join","privateKey","importPKCS8","jwt","SignJWT","scope","setProtectedHeader","alg","setIssuedAt","setExpirationTime","setIssuer","client_email","setSubject","setAudience","sign","response","fetch","method","headers","body","URLSearchParams","grant_type","assertion","ok","error","json","error_description","access_token","message","getAccessTokenFromServiceAccount","createSessionPath","projectId","location","agentId","sessionId","extractRichContent","responseMessages","richContent","msg","payload","fields","richContentValue","listValue","values","map","v","item","structValue","type","options","stringValue","opt","text","random","toString","substr","dfLocation","split","apiEndpoint","dfProjectId","dfAgentId","request","queryInput","languageCode","Authorization","JSON","stringify","catch","status","data","welcomeMessage","queryResult","textMessages","filter","fulfillmentText","session_id","errorMessage","errorText","errorData","parse","responseText","handoff","parameters","boolValue","source","timestamp","toISOString"],"mappings":"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"}
|
|
@@ -1,282 +0,0 @@
|
|
|
1
|
-
import { importPKCS8 } from "../node_modules/jose/dist/browser/key/import.esm.js";
|
|
2
|
-
import { SignJWT } from "../node_modules/jose/dist/browser/jwt/sign.esm.js";
|
|
3
|
-
async function getAccessTokenFromServiceAccount(serviceAccountKey) {
|
|
4
|
-
const now = Math.floor(Date.now() / 1e3);
|
|
5
|
-
let privateKeyPem = serviceAccountKey.private_key;
|
|
6
|
-
if (privateKeyPem) {
|
|
7
|
-
privateKeyPem = privateKeyPem.trim();
|
|
8
|
-
if (!privateKeyPem.includes("-----BEGIN")) {
|
|
9
|
-
const keyContent = privateKeyPem.replace(/\s/g, "");
|
|
10
|
-
const formattedKey = keyContent.match(/.{1,64}/g)?.join("\n") || keyContent;
|
|
11
|
-
privateKeyPem = `-----BEGIN PRIVATE KEY-----
|
|
12
|
-
${formattedKey}
|
|
13
|
-
-----END PRIVATE KEY-----`;
|
|
14
|
-
} else {
|
|
15
|
-
privateKeyPem = privateKeyPem.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
16
|
-
if (privateKeyPem.includes("BEGIN RSA PRIVATE KEY")) {
|
|
17
|
-
throw new Error(
|
|
18
|
-
"Private key is in PKCS#1 format (RSA PRIVATE KEY). Please download a new service account key from Google Cloud Console. The key should be in PKCS#8 format (PRIVATE KEY)."
|
|
19
|
-
);
|
|
20
|
-
}
|
|
21
|
-
const keyMatch = privateKeyPem.match(/-----BEGIN PRIVATE KEY-----\n?([\s\S]*?)\n?-----END PRIVATE KEY-----/);
|
|
22
|
-
if (keyMatch) {
|
|
23
|
-
const keyContent = keyMatch[1].replace(/\s/g, "");
|
|
24
|
-
if (!keyContent.includes("\n") || keyContent.length > 64) {
|
|
25
|
-
const formattedKey = keyContent.match(/.{1,64}/g)?.join("\n") || keyContent;
|
|
26
|
-
privateKeyPem = `-----BEGIN PRIVATE KEY-----
|
|
27
|
-
${formattedKey}
|
|
28
|
-
-----END PRIVATE KEY-----`;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
} else {
|
|
33
|
-
throw new Error("Private key is missing from service account key");
|
|
34
|
-
}
|
|
35
|
-
try {
|
|
36
|
-
const privateKey = await importPKCS8(privateKeyPem, "RS256");
|
|
37
|
-
const jwt = await new SignJWT({
|
|
38
|
-
scope: "https://www.googleapis.com/auth/cloud-platform"
|
|
39
|
-
}).setProtectedHeader({ alg: "RS256" }).setIssuedAt(now).setExpirationTime(now + 3600).setIssuer(serviceAccountKey.client_email).setSubject(serviceAccountKey.client_email).setAudience("https://oauth2.googleapis.com/token").sign(privateKey);
|
|
40
|
-
const response = await fetch("https://oauth2.googleapis.com/token", {
|
|
41
|
-
method: "POST",
|
|
42
|
-
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
43
|
-
body: new URLSearchParams({
|
|
44
|
-
grant_type: "urn:ietf:params:oauth:grant-type:jwt-bearer",
|
|
45
|
-
assertion: jwt
|
|
46
|
-
})
|
|
47
|
-
});
|
|
48
|
-
if (!response.ok) {
|
|
49
|
-
const error = await response.json();
|
|
50
|
-
throw new Error(error.error_description || "Failed to get access token");
|
|
51
|
-
}
|
|
52
|
-
const data = await response.json();
|
|
53
|
-
return data.access_token;
|
|
54
|
-
} catch (error) {
|
|
55
|
-
if (error.message && error.message.includes("pkcs8")) {
|
|
56
|
-
throw new Error(
|
|
57
|
-
"Invalid private key format. The service account key must be in PKCS#8 format. Please ensure your service account key JSON file has a properly formatted private_key field. If you downloaded the key from Google Cloud Console, it should already be in the correct format."
|
|
58
|
-
);
|
|
59
|
-
}
|
|
60
|
-
throw error;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
async function getAccessToken(config) {
|
|
64
|
-
if (config.accessToken) {
|
|
65
|
-
return config.accessToken;
|
|
66
|
-
}
|
|
67
|
-
if (!config.serviceAccountKey) {
|
|
68
|
-
throw new Error("Either serviceAccountKey or accessToken must be provided");
|
|
69
|
-
}
|
|
70
|
-
return await getAccessTokenFromServiceAccount(config.serviceAccountKey);
|
|
71
|
-
}
|
|
72
|
-
function createSessionPath(projectId, location, agentId, sessionId) {
|
|
73
|
-
return `projects/${projectId}/locations/${location}/agents/${agentId}/sessions/${sessionId}`;
|
|
74
|
-
}
|
|
75
|
-
function extractRichContent(responseMessages) {
|
|
76
|
-
let richContent = null;
|
|
77
|
-
for (const msg of responseMessages) {
|
|
78
|
-
if (msg.payload) {
|
|
79
|
-
if (msg.payload.richContent) {
|
|
80
|
-
richContent = msg.payload.richContent;
|
|
81
|
-
break;
|
|
82
|
-
}
|
|
83
|
-
if (msg.payload.fields && msg.payload.fields.richContent) {
|
|
84
|
-
const richContentValue = msg.payload.fields.richContent;
|
|
85
|
-
if (richContentValue.listValue && richContentValue.listValue.values) {
|
|
86
|
-
richContent = richContentValue.listValue.values.map((v) => {
|
|
87
|
-
if (v.listValue && v.listValue.values) {
|
|
88
|
-
return v.listValue.values.map((item) => {
|
|
89
|
-
if (item.structValue && item.structValue.fields) {
|
|
90
|
-
const fields = item.structValue.fields;
|
|
91
|
-
if (fields.type && fields.options) {
|
|
92
|
-
return {
|
|
93
|
-
type: fields.type.stringValue || fields.type,
|
|
94
|
-
options: fields.options.listValue ? fields.options.listValue.values.map((opt) => ({
|
|
95
|
-
text: opt.structValue?.fields?.text?.stringValue || "",
|
|
96
|
-
payload: opt.structValue?.fields?.payload?.stringValue || ""
|
|
97
|
-
})) : []
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
return item;
|
|
102
|
-
});
|
|
103
|
-
}
|
|
104
|
-
return v;
|
|
105
|
-
});
|
|
106
|
-
} else if (typeof richContentValue === "object" && !richContentValue.listValue) {
|
|
107
|
-
richContent = richContentValue;
|
|
108
|
-
}
|
|
109
|
-
break;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
return richContent;
|
|
114
|
-
}
|
|
115
|
-
async function createDialogflowSession(config) {
|
|
116
|
-
try {
|
|
117
|
-
const accessToken = await getAccessToken(config);
|
|
118
|
-
const sessionId = `session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
119
|
-
const location = config.dfLocation.split(" ")[0].trim();
|
|
120
|
-
const sessionPath = createSessionPath(
|
|
121
|
-
config.dfProjectId,
|
|
122
|
-
location,
|
|
123
|
-
config.dfAgentId,
|
|
124
|
-
sessionId
|
|
125
|
-
);
|
|
126
|
-
const apiEndpoint = `https://${location}-dialogflow.googleapis.com/v3/${sessionPath}:detectIntent`;
|
|
127
|
-
const request = {
|
|
128
|
-
queryInput: {
|
|
129
|
-
text: {
|
|
130
|
-
text: "hello"
|
|
131
|
-
},
|
|
132
|
-
languageCode: config.languageCode || "en"
|
|
133
|
-
}
|
|
134
|
-
};
|
|
135
|
-
const response = await fetch(apiEndpoint, {
|
|
136
|
-
method: "POST",
|
|
137
|
-
headers: {
|
|
138
|
-
"Authorization": `Bearer ${accessToken}`,
|
|
139
|
-
"Content-Type": "application/json"
|
|
140
|
-
},
|
|
141
|
-
body: JSON.stringify(request)
|
|
142
|
-
});
|
|
143
|
-
if (!response.ok) {
|
|
144
|
-
const error = await response.json().catch(() => ({}));
|
|
145
|
-
throw new Error(error.error?.message || `HTTP error! status: ${response.status}`);
|
|
146
|
-
}
|
|
147
|
-
const data = await response.json();
|
|
148
|
-
let welcomeMessage = "Hello! I'm BlockSpark AI Assistant. How can I help you today?";
|
|
149
|
-
let richContent = null;
|
|
150
|
-
if (data.queryResult?.responseMessages) {
|
|
151
|
-
const textMessages = data.queryResult.responseMessages.filter((msg) => msg.text).map((msg) => msg.text.text.join(" "));
|
|
152
|
-
if (textMessages.length > 0) {
|
|
153
|
-
welcomeMessage = textMessages.join(" ");
|
|
154
|
-
}
|
|
155
|
-
richContent = extractRichContent(data.queryResult.responseMessages);
|
|
156
|
-
} else if (data.queryResult?.fulfillmentText) {
|
|
157
|
-
welcomeMessage = data.queryResult.fulfillmentText;
|
|
158
|
-
}
|
|
159
|
-
return {
|
|
160
|
-
session_id: sessionId,
|
|
161
|
-
message: welcomeMessage,
|
|
162
|
-
...richContent && { richContent }
|
|
163
|
-
};
|
|
164
|
-
} catch (error) {
|
|
165
|
-
console.error("Error creating Dialogflow session:", error);
|
|
166
|
-
const errorMessage = error.message || "Failed to create session";
|
|
167
|
-
if (errorMessage.includes("401") || errorMessage.includes("Unauthorized")) {
|
|
168
|
-
throw new Error("Authentication failed. Please check your service account key or access token.");
|
|
169
|
-
} else if (errorMessage.includes("403") || errorMessage.includes("Forbidden")) {
|
|
170
|
-
throw new Error("Access forbidden. Please check your Dialogflow API permissions.");
|
|
171
|
-
} else if (errorMessage.includes("404") || errorMessage.includes("Not Found")) {
|
|
172
|
-
throw new Error("Dialogflow agent not found. Please check your project ID, location, and agent ID.");
|
|
173
|
-
}
|
|
174
|
-
throw new Error(errorMessage);
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
async function sendDialogflowMessage(message, sessionId, config) {
|
|
178
|
-
try {
|
|
179
|
-
const accessToken = await getAccessToken(config);
|
|
180
|
-
const location = config.dfLocation.split(" ")[0].trim();
|
|
181
|
-
const sessionPath = createSessionPath(
|
|
182
|
-
config.dfProjectId,
|
|
183
|
-
location,
|
|
184
|
-
config.dfAgentId,
|
|
185
|
-
sessionId
|
|
186
|
-
);
|
|
187
|
-
const apiEndpoint = `https://${location}-dialogflow.googleapis.com/v3/${sessionPath}:detectIntent`;
|
|
188
|
-
const request = {
|
|
189
|
-
queryInput: {
|
|
190
|
-
text: {
|
|
191
|
-
text: message.trim()
|
|
192
|
-
},
|
|
193
|
-
languageCode: config.languageCode || "en"
|
|
194
|
-
}
|
|
195
|
-
};
|
|
196
|
-
const response = await fetch(apiEndpoint, {
|
|
197
|
-
method: "POST",
|
|
198
|
-
headers: {
|
|
199
|
-
"Authorization": `Bearer ${accessToken}`,
|
|
200
|
-
"Content-Type": "application/json"
|
|
201
|
-
},
|
|
202
|
-
body: JSON.stringify(request)
|
|
203
|
-
});
|
|
204
|
-
if (!response.ok) {
|
|
205
|
-
const errorText = await response.text();
|
|
206
|
-
let errorData = {};
|
|
207
|
-
try {
|
|
208
|
-
errorData = JSON.parse(errorText);
|
|
209
|
-
} catch {
|
|
210
|
-
errorData = { message: errorText || `HTTP ${response.status}` };
|
|
211
|
-
}
|
|
212
|
-
const errorMessage = errorData.error?.message || errorData.message || `HTTP error! status: ${response.status}`;
|
|
213
|
-
console.error("Dialogflow API Error (sendMessage):", {
|
|
214
|
-
status: response.status,
|
|
215
|
-
statusText: response.statusText,
|
|
216
|
-
error: errorData,
|
|
217
|
-
endpoint: apiEndpoint
|
|
218
|
-
});
|
|
219
|
-
throw new Error(errorMessage);
|
|
220
|
-
}
|
|
221
|
-
const data = await response.json();
|
|
222
|
-
let responseText = "I'm sorry, I didn't understand that. Could you please rephrase?";
|
|
223
|
-
let richContent = null;
|
|
224
|
-
let handoff = false;
|
|
225
|
-
if (data.queryResult?.parameters?.fields?.handoff?.boolValue === true) {
|
|
226
|
-
handoff = true;
|
|
227
|
-
} else if (data.queryResult?.responseMessages) {
|
|
228
|
-
for (const msg of data.queryResult.responseMessages) {
|
|
229
|
-
if (msg.payload) {
|
|
230
|
-
if (typeof msg.payload === "object") {
|
|
231
|
-
if (msg.payload.handoff === true) {
|
|
232
|
-
handoff = true;
|
|
233
|
-
break;
|
|
234
|
-
}
|
|
235
|
-
if (msg.payload.fields?.handoff?.boolValue === true) {
|
|
236
|
-
handoff = true;
|
|
237
|
-
break;
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
if (data.handoff === true) {
|
|
244
|
-
handoff = true;
|
|
245
|
-
}
|
|
246
|
-
if (data.queryResult?.responseMessages) {
|
|
247
|
-
const textMessages = data.queryResult.responseMessages.filter((msg) => msg.text).map((msg) => msg.text.text.join(" "));
|
|
248
|
-
if (textMessages.length > 0) {
|
|
249
|
-
responseText = textMessages.join(" ");
|
|
250
|
-
}
|
|
251
|
-
richContent = extractRichContent(data.queryResult.responseMessages);
|
|
252
|
-
} else if (data.queryResult?.fulfillmentText) {
|
|
253
|
-
responseText = data.queryResult.fulfillmentText;
|
|
254
|
-
}
|
|
255
|
-
return {
|
|
256
|
-
response: responseText,
|
|
257
|
-
session_id: sessionId,
|
|
258
|
-
source: "dialogflow",
|
|
259
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
260
|
-
...richContent && { richContent },
|
|
261
|
-
...handoff && { handoff: true }
|
|
262
|
-
};
|
|
263
|
-
} catch (error) {
|
|
264
|
-
console.error("Error sending message to Dialogflow:", error);
|
|
265
|
-
const errorMessage = error.message || "Failed to send message";
|
|
266
|
-
if (errorMessage.includes("401") || errorMessage.includes("Unauthorized")) {
|
|
267
|
-
throw new Error("Authentication failed. Please check your service account key or access token.");
|
|
268
|
-
} else if (errorMessage.includes("403") || errorMessage.includes("Forbidden")) {
|
|
269
|
-
throw new Error("Access forbidden. Please check your Dialogflow API permissions.");
|
|
270
|
-
} else if (errorMessage.includes("404") || errorMessage.includes("Not Found")) {
|
|
271
|
-
throw new Error("Dialogflow agent not found. Please check your project ID, location, and agent ID.");
|
|
272
|
-
} else if (errorMessage.includes("CORS")) {
|
|
273
|
-
throw new Error("CORS error. Dialogflow API may not allow browser requests. Consider using a backend proxy.");
|
|
274
|
-
}
|
|
275
|
-
throw new Error(errorMessage);
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
export {
|
|
279
|
-
createDialogflowSession,
|
|
280
|
-
sendDialogflowMessage
|
|
281
|
-
};
|
|
282
|
-
//# sourceMappingURL=dialogflowClient.esm.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"dialogflowClient.esm.js","sources":["../../src/services/dialogflowClient.ts"],"sourcesContent":["// services/dialogflowClient.ts\nimport { SignJWT, importPKCS8 } from 'jose';\n// dotenv removed - environment variables should be handled by the consuming application\n\n\nexport interface DialogflowConfig {\n dfProjectId: string;\n dfLocation: string;\n dfAgentId: string;\n serviceAccountKey?: any; // Service account JSON object\n accessToken?: string; // Alternative: provide access token directly\n languageCode?: string;\n}\n\nexport interface SessionResponse {\n session_id: string;\n message: string;\n richContent?: any;\n}\n\nexport interface ChatResponse {\n response: string;\n session_id: string;\n source: string;\n timestamp: string;\n richContent?: any;\n handoff?: boolean;\n}\n\n// Helper to get access token from service account using Web Crypto API\nasync function getAccessTokenFromServiceAccount(serviceAccountKey: any): Promise<string> {\n const now = Math.floor(Date.now() / 1000);\n \n // Format the private key - ensure it's properly formatted for PKCS#8\n let privateKeyPem = serviceAccountKey.private_key;\n \n // Google service account keys should already be in PKCS#8 format\n // But we need to ensure proper formatting with newlines\n if (privateKeyPem) {\n // Remove any existing whitespace/newlines\n privateKeyPem = privateKeyPem.trim();\n \n // If it doesn't have headers, it's just the base64 content\n if (!privateKeyPem.includes('-----BEGIN')) {\n // Wrap the base64 content with proper headers\n // Split into 64-character lines for proper PEM format\n const keyContent = privateKeyPem.replace(/\\s/g, '');\n const formattedKey = keyContent.match(/.{1,64}/g)?.join('\\n') || keyContent;\n privateKeyPem = `-----BEGIN PRIVATE KEY-----\\n${formattedKey}\\n-----END PRIVATE KEY-----`;\n } else {\n // Key has headers, but ensure proper line breaks\n // Normalize line breaks to \\n\n privateKeyPem = privateKeyPem.replace(/\\r\\n/g, '\\n').replace(/\\r/g, '\\n');\n \n // If it's RSA PRIVATE KEY (PKCS#1), we need to note that jose can't convert it\n // Google service accounts should provide PKCS#8, but if not, we'll try to use as-is\n if (privateKeyPem.includes('BEGIN RSA PRIVATE KEY')) {\n throw new Error(\n 'Private key is in PKCS#1 format (RSA PRIVATE KEY). ' +\n 'Please download a new service account key from Google Cloud Console. ' +\n 'The key should be in PKCS#8 format (PRIVATE KEY).'\n );\n }\n \n // Ensure the key content is properly formatted (64 chars per line)\n const keyMatch = privateKeyPem.match(/-----BEGIN PRIVATE KEY-----\\n?([\\s\\S]*?)\\n?-----END PRIVATE KEY-----/);\n if (keyMatch) {\n const keyContent = keyMatch[1].replace(/\\s/g, '');\n // Check if already properly formatted (has newlines every 64 chars)\n if (!keyContent.includes('\\n') || keyContent.length > 64) {\n const formattedKey = keyContent.match(/.{1,64}/g)?.join('\\n') || keyContent;\n privateKeyPem = `-----BEGIN PRIVATE KEY-----\\n${formattedKey}\\n-----END PRIVATE KEY-----`;\n }\n }\n }\n } else {\n throw new Error('Private key is missing from service account key');\n }\n \n try {\n // Import the private key (jose expects PKCS#8 format)\n const privateKey = await importPKCS8(privateKeyPem, 'RS256');\n \n // Create JWT\n const jwt = await new SignJWT({\n scope: 'https://www.googleapis.com/auth/cloud-platform',\n })\n .setProtectedHeader({ alg: 'RS256' })\n .setIssuedAt(now)\n .setExpirationTime(now + 3600)\n .setIssuer(serviceAccountKey.client_email)\n .setSubject(serviceAccountKey.client_email)\n .setAudience('https://oauth2.googleapis.com/token')\n .sign(privateKey);\n\n // Exchange JWT for access token\n const response = await fetch('https://oauth2.googleapis.com/token', {\n method: 'POST',\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n body: new URLSearchParams({\n grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',\n assertion: jwt,\n }),\n });\n\n if (!response.ok) {\n const error = await response.json();\n throw new Error(error.error_description || 'Failed to get access token');\n }\n\n const data = await response.json();\n return data.access_token;\n } catch (error: any) {\n if (error.message && error.message.includes('pkcs8')) {\n throw new Error(\n 'Invalid private key format. The service account key must be in PKCS#8 format. ' +\n 'Please ensure your service account key JSON file has a properly formatted private_key field. ' +\n 'If you downloaded the key from Google Cloud Console, it should already be in the correct format.'\n );\n }\n throw error;\n }\n}\n\n// Get access token (either from service account or use provided token)\nasync function getAccessToken(config: DialogflowConfig): Promise<string> {\n if (config.accessToken) {\n return config.accessToken;\n }\n \n if (!config.serviceAccountKey) {\n throw new Error('Either serviceAccountKey or accessToken must be provided');\n }\n\n return await getAccessTokenFromServiceAccount(config.serviceAccountKey);\n}\n\n// Create session path\nfunction createSessionPath(projectId: string, location: string, agentId: string, sessionId: string): string {\n return `projects/${projectId}/locations/${location}/agents/${agentId}/sessions/${sessionId}`;\n}\n\n// Extract rich content from Dialogflow response\nfunction extractRichContent(responseMessages: any[]): any {\n let richContent = null;\n \n for (const msg of responseMessages) {\n if (msg.payload) {\n if (msg.payload.richContent) {\n richContent = msg.payload.richContent;\n break;\n }\n if (msg.payload.fields && msg.payload.fields.richContent) {\n const richContentValue = msg.payload.fields.richContent;\n if (richContentValue.listValue && richContentValue.listValue.values) {\n richContent = richContentValue.listValue.values.map((v: any) => {\n if (v.listValue && v.listValue.values) {\n return v.listValue.values.map((item: any) => {\n if (item.structValue && item.structValue.fields) {\n const fields = item.structValue.fields;\n if (fields.type && fields.options) {\n return {\n type: fields.type.stringValue || fields.type,\n options: fields.options.listValue\n ? fields.options.listValue.values.map((opt: any) => ({\n text: opt.structValue?.fields?.text?.stringValue || '',\n payload: opt.structValue?.fields?.payload?.stringValue || '',\n }))\n : [],\n };\n }\n }\n return item;\n });\n }\n return v;\n });\n } else if (typeof richContentValue === 'object' && !richContentValue.listValue) {\n richContent = richContentValue;\n }\n break;\n }\n }\n }\n \n return richContent;\n}\n\n/**\n * Create a new Dialogflow session\n * @param config - Dialogflow configuration\n * @returns Promise with session ID and welcome message\n */\nexport async function createDialogflowSession(config: DialogflowConfig): Promise<SessionResponse> {\n try {\n const accessToken = await getAccessToken(config);\n const sessionId = `session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n const location = config.dfLocation.split(' ')[0].trim(); // Extract just the location code\n const sessionPath = createSessionPath(\n config.dfProjectId,\n location,\n config.dfAgentId,\n sessionId\n );\n\n const apiEndpoint = `https://${location}-dialogflow.googleapis.com/v3/${sessionPath}:detectIntent`;\n\n // Get welcome message\n const request = {\n queryInput: {\n text: {\n text: 'hello',\n },\n languageCode: config.languageCode || 'en',\n },\n };\n\n const response = await fetch(apiEndpoint, {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${accessToken}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(request),\n });\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({}));\n throw new Error(error.error?.message || `HTTP error! status: ${response.status}`);\n }\n\n const data = await response.json();\n \n let welcomeMessage = \"Hello! I'm BlockSpark AI Assistant. How can I help you today?\";\n let richContent = null;\n\n if (data.queryResult?.responseMessages) {\n const textMessages = data.queryResult.responseMessages\n .filter((msg: any) => msg.text)\n .map((msg: any) => msg.text.text.join(' '));\n \n if (textMessages.length > 0) {\n welcomeMessage = textMessages.join(' ');\n }\n\n richContent = extractRichContent(data.queryResult.responseMessages);\n } else if (data.queryResult?.fulfillmentText) {\n welcomeMessage = data.queryResult.fulfillmentText;\n }\n\n return {\n session_id: sessionId,\n message: welcomeMessage,\n ...(richContent && { richContent }),\n };\n } catch (error: any) {\n console.error('Error creating Dialogflow session:', error);\n const errorMessage = error.message || 'Failed to create session';\n if (errorMessage.includes('401') || errorMessage.includes('Unauthorized')) {\n throw new Error('Authentication failed. Please check your service account key or access token.');\n } else if (errorMessage.includes('403') || errorMessage.includes('Forbidden')) {\n throw new Error('Access forbidden. Please check your Dialogflow API permissions.');\n } else if (errorMessage.includes('404') || errorMessage.includes('Not Found')) {\n throw new Error('Dialogflow agent not found. Please check your project ID, location, and agent ID.');\n }\n throw new Error(errorMessage);\n }\n}\n\n/**\n * Send a message to Dialogflow\n * @param message - The user's message\n * @param sessionId - The session ID\n * @param config - Dialogflow configuration\n * @returns Promise with bot response\n */\nexport async function sendDialogflowMessage(\n message: string,\n sessionId: string,\n config: DialogflowConfig\n): Promise<ChatResponse> {\n try {\n const accessToken = await getAccessToken(config);\n const location = config.dfLocation.split(' ')[0].trim(); // Extract just the location code\n const sessionPath = createSessionPath(\n config.dfProjectId,\n location,\n config.dfAgentId,\n sessionId\n );\n\n const apiEndpoint = `https://${location}-dialogflow.googleapis.com/v3/${sessionPath}:detectIntent`;\n\n const request = {\n queryInput: {\n text: {\n text: message.trim(),\n },\n languageCode: config.languageCode || 'en',\n },\n };\n\n const response = await fetch(apiEndpoint, {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${accessToken}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(request),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n let errorData: any = {};\n try {\n errorData = JSON.parse(errorText);\n } catch {\n errorData = { message: errorText || `HTTP ${response.status}` };\n }\n const errorMessage = errorData.error?.message || errorData.message || `HTTP error! status: ${response.status}`;\n console.error('Dialogflow API Error (sendMessage):', {\n status: response.status,\n statusText: response.statusText,\n error: errorData,\n endpoint: apiEndpoint,\n });\n throw new Error(errorMessage);\n }\n\n const data = await response.json();\n\n let responseText = \"I'm sorry, I didn't understand that. Could you please rephrase?\";\n let richContent = null;\n let handoff = false;\n\n // Check for handoff trigger\n if (data.queryResult?.parameters?.fields?.handoff?.boolValue === true) {\n handoff = true;\n } else if (data.queryResult?.responseMessages) {\n // Check in responseMessages payload\n for (const msg of data.queryResult.responseMessages) {\n if (msg.payload) {\n if (typeof msg.payload === 'object') {\n if (msg.payload.handoff === true) {\n handoff = true;\n break;\n }\n if (msg.payload.fields?.handoff?.boolValue === true) {\n handoff = true;\n break;\n }\n }\n }\n }\n }\n \n // Check at root level\n if (data.handoff === true) {\n handoff = true;\n }\n\n if (data.queryResult?.responseMessages) {\n const textMessages = data.queryResult.responseMessages\n .filter((msg: any) => msg.text)\n .map((msg: any) => msg.text.text.join(' '));\n \n if (textMessages.length > 0) {\n responseText = textMessages.join(' ');\n }\n\n richContent = extractRichContent(data.queryResult.responseMessages);\n } else if (data.queryResult?.fulfillmentText) {\n responseText = data.queryResult.fulfillmentText;\n }\n\n return {\n response: responseText,\n session_id: sessionId,\n source: 'dialogflow',\n timestamp: new Date().toISOString(),\n ...(richContent && { richContent }),\n ...(handoff && { handoff: true }),\n };\n } catch (error: any) {\n console.error('Error sending message to Dialogflow:', error);\n const errorMessage = error.message || 'Failed to send message';\n if (errorMessage.includes('401') || errorMessage.includes('Unauthorized')) {\n throw new Error('Authentication failed. Please check your service account key or access token.');\n } else if (errorMessage.includes('403') || errorMessage.includes('Forbidden')) {\n throw new Error('Access forbidden. Please check your Dialogflow API permissions.');\n } else if (errorMessage.includes('404') || errorMessage.includes('Not Found')) {\n throw new Error('Dialogflow agent not found. Please check your project ID, location, and agent ID.');\n } else if (errorMessage.includes('CORS')) {\n throw new Error('CORS error. Dialogflow API may not allow browser requests. Consider using a backend proxy.');\n }\n throw new Error(errorMessage);\n }\n}\n\n"],"names":[],"mappings":"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"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e="chat_session_id";class s{constructor(){this.sessionId=null,this.sessionId=this.loadSessionId()}loadSessionId(){return"undefined"!=typeof localStorage?localStorage.getItem(e):null}saveSessionId(s){this.sessionId=s,"undefined"!=typeof localStorage&&(s?localStorage.setItem(e,s):localStorage.removeItem(e))}updateSessionFromResponse(e){const s=e?.data?.session_id||e?.session_id;s&&"string"==typeof s&&this.saveSessionId(s)}getSessionId(){return this.sessionId||""}getSessionHeader(){return{"X-Session-ID":this.getSessionId()}}}let o=null;exports.getSessionManager=function(){return o||(o=new s),o};
|
|
2
|
-
//# sourceMappingURL=sessionManager.cjs.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sessionManager.cjs.js","sources":["../../src/services/sessionManager.ts"],"sourcesContent":["// services/sessionManager.ts\n\nconst SESSION_KEY = 'chat_session_id';\n\nclass ChatSessionManager {\n private sessionId: string | null = null;\n\n constructor() {\n this.sessionId = this.loadSessionId();\n }\n\n loadSessionId(): string | null {\n if (typeof localStorage !== 'undefined') {\n return localStorage.getItem(SESSION_KEY);\n }\n return null;\n }\n\n saveSessionId(sessionId: string | null): void {\n this.sessionId = sessionId;\n if (typeof localStorage !== 'undefined') {\n if (sessionId) {\n localStorage.setItem(SESSION_KEY, sessionId);\n } else {\n localStorage.removeItem(SESSION_KEY);\n }\n }\n }\n\n updateSessionFromResponse(responseData: any): void {\n const sid = responseData?.data?.session_id || responseData?.session_id;\n if (sid && typeof sid === 'string') {\n this.saveSessionId(sid);\n }\n }\n\n getSessionId(): string {\n return this.sessionId || '';\n }\n\n getSessionHeader(): Record<string, string> {\n return {\n 'X-Session-ID': this.getSessionId()\n };\n }\n}\n\n// Export singleton instance\nlet sessionManagerInstance: ChatSessionManager | null = null;\n\nexport function getSessionManager(): ChatSessionManager {\n if (!sessionManagerInstance) {\n sessionManagerInstance = new ChatSessionManager();\n }\n return sessionManagerInstance;\n}\n\nexport function createSessionManager(): ChatSessionManager {\n return new ChatSessionManager();\n}\n\nexport default ChatSessionManager;\n"],"names":["SESSION_KEY","ChatSessionManager","constructor","this","sessionId","loadSessionId","localStorage","getItem","saveSessionId","setItem","removeItem","updateSessionFromResponse","responseData","sid","data","session_id","getSessionId","getSessionHeader","sessionManagerInstance"],"mappings":"gFAEA,MAAMA,EAAc,kBAEpB,MAAMC,EAGJ,WAAAC,GAFAC,KAAQC,UAA2B,KAGjCD,KAAKC,UAAYD,KAAKE,eACxB,CAEA,aAAAA,GACE,MAA4B,oBAAjBC,aACFA,aAAaC,QAAQP,GAEvB,IACT,CAEA,aAAAQ,CAAcJ,GACZD,KAAKC,UAAYA,EACW,oBAAjBE,eACLF,EACFE,aAAaG,QAAQT,EAAaI,GAElCE,aAAaI,WAAWV,GAG9B,CAEA,yBAAAW,CAA0BC,GACxB,MAAMC,EAAMD,GAAcE,MAAMC,YAAcH,GAAcG,WACxDF,GAAsB,iBAARA,GAChBV,KAAKK,cAAcK,EAEvB,CAEA,YAAAG,GACE,OAAOb,KAAKC,WAAa,EAC3B,CAEA,gBAAAa,GACE,MAAO,CACL,eAAgBd,KAAKa,eAEzB,EAIF,IAAIE,EAAoD,+BAEjD,WAIL,OAHKA,IACHA,EAAyB,IAAIjB,GAExBiB,CACT"}
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
const SESSION_KEY = "chat_session_id";
|
|
2
|
-
class ChatSessionManager {
|
|
3
|
-
constructor() {
|
|
4
|
-
this.sessionId = null;
|
|
5
|
-
this.sessionId = this.loadSessionId();
|
|
6
|
-
}
|
|
7
|
-
loadSessionId() {
|
|
8
|
-
if (typeof localStorage !== "undefined") {
|
|
9
|
-
return localStorage.getItem(SESSION_KEY);
|
|
10
|
-
}
|
|
11
|
-
return null;
|
|
12
|
-
}
|
|
13
|
-
saveSessionId(sessionId) {
|
|
14
|
-
this.sessionId = sessionId;
|
|
15
|
-
if (typeof localStorage !== "undefined") {
|
|
16
|
-
if (sessionId) {
|
|
17
|
-
localStorage.setItem(SESSION_KEY, sessionId);
|
|
18
|
-
} else {
|
|
19
|
-
localStorage.removeItem(SESSION_KEY);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
updateSessionFromResponse(responseData) {
|
|
24
|
-
const sid = responseData?.data?.session_id || responseData?.session_id;
|
|
25
|
-
if (sid && typeof sid === "string") {
|
|
26
|
-
this.saveSessionId(sid);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
getSessionId() {
|
|
30
|
-
return this.sessionId || "";
|
|
31
|
-
}
|
|
32
|
-
getSessionHeader() {
|
|
33
|
-
return {
|
|
34
|
-
"X-Session-ID": this.getSessionId()
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
let sessionManagerInstance = null;
|
|
39
|
-
function getSessionManager() {
|
|
40
|
-
if (!sessionManagerInstance) {
|
|
41
|
-
sessionManagerInstance = new ChatSessionManager();
|
|
42
|
-
}
|
|
43
|
-
return sessionManagerInstance;
|
|
44
|
-
}
|
|
45
|
-
export {
|
|
46
|
-
getSessionManager
|
|
47
|
-
};
|
|
48
|
-
//# sourceMappingURL=sessionManager.esm.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sessionManager.esm.js","sources":["../../src/services/sessionManager.ts"],"sourcesContent":["// services/sessionManager.ts\n\nconst SESSION_KEY = 'chat_session_id';\n\nclass ChatSessionManager {\n private sessionId: string | null = null;\n\n constructor() {\n this.sessionId = this.loadSessionId();\n }\n\n loadSessionId(): string | null {\n if (typeof localStorage !== 'undefined') {\n return localStorage.getItem(SESSION_KEY);\n }\n return null;\n }\n\n saveSessionId(sessionId: string | null): void {\n this.sessionId = sessionId;\n if (typeof localStorage !== 'undefined') {\n if (sessionId) {\n localStorage.setItem(SESSION_KEY, sessionId);\n } else {\n localStorage.removeItem(SESSION_KEY);\n }\n }\n }\n\n updateSessionFromResponse(responseData: any): void {\n const sid = responseData?.data?.session_id || responseData?.session_id;\n if (sid && typeof sid === 'string') {\n this.saveSessionId(sid);\n }\n }\n\n getSessionId(): string {\n return this.sessionId || '';\n }\n\n getSessionHeader(): Record<string, string> {\n return {\n 'X-Session-ID': this.getSessionId()\n };\n }\n}\n\n// Export singleton instance\nlet sessionManagerInstance: ChatSessionManager | null = null;\n\nexport function getSessionManager(): ChatSessionManager {\n if (!sessionManagerInstance) {\n sessionManagerInstance = new ChatSessionManager();\n }\n return sessionManagerInstance;\n}\n\nexport function createSessionManager(): ChatSessionManager {\n return new ChatSessionManager();\n}\n\nexport default ChatSessionManager;\n"],"names":[],"mappings":"AAEA,MAAM,cAAc;AAEpB,MAAM,mBAAmB;AAAA,EAGvB,cAAc;AAFd,SAAQ,YAA2B;AAGjC,SAAK,YAAY,KAAK,cAAA;AAAA,EACxB;AAAA,EAEA,gBAA+B;AAC7B,QAAI,OAAO,iBAAiB,aAAa;AACvC,aAAO,aAAa,QAAQ,WAAW;AAAA,IACzC;AACA,WAAO;AAAA,EACT;AAAA,EAEA,cAAc,WAAgC;AAC5C,SAAK,YAAY;AACjB,QAAI,OAAO,iBAAiB,aAAa;AACvC,UAAI,WAAW;AACb,qBAAa,QAAQ,aAAa,SAAS;AAAA,MAC7C,OAAO;AACL,qBAAa,WAAW,WAAW;AAAA,MACrC;AAAA,IACF;AAAA,EACF;AAAA,EAEA,0BAA0B,cAAyB;AACjD,UAAM,MAAM,cAAc,MAAM,cAAc,cAAc;AAC5D,QAAI,OAAO,OAAO,QAAQ,UAAU;AAClC,WAAK,cAAc,GAAG;AAAA,IACxB;AAAA,EACF;AAAA,EAEA,eAAuB;AACrB,WAAO,KAAK,aAAa;AAAA,EAC3B;AAAA,EAEA,mBAA2C;AACzC,WAAO;AAAA,MACL,gBAAgB,KAAK,aAAA;AAAA,IAAa;AAAA,EAEtC;AACF;AAGA,IAAI,yBAAoD;AAEjD,SAAS,oBAAwC;AACtD,MAAI,CAAC,wBAAwB;AAC3B,6BAAyB,IAAI,mBAAA;AAAA,EAC/B;AACA,SAAO;AACT;"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
"use strict";Object.create,Object.defineProperty,Object.getOwnPropertyDescriptor,Object.getOwnPropertyNames,Object.getPrototypeOf,Object.prototype.hasOwnProperty;Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});var e="undefined"!=typeof document?document.currentScript:null;function r(){const r="undefined"==typeof window;if("undefined"!=typeof process&&process.env?.NEXT_RUNTIME)return{name:"next",version:process.env.NEXT_VERSION,isSSR:r};if("undefined"!=typeof process&&(process.env?.NUXT||globalThis.__NUXT__))return{name:"nuxt",version:process.env.NUXT_VERSION,isSSR:r};if(void 0!=={url:"undefined"==typeof document?require("url").pathToFileURL(__filename).href:e&&"SCRIPT"===e.tagName.toUpperCase()&&e.src||new URL("utils/frameworkDetector.cjs.js",document.baseURI).href}){const n={url:"undefined"==typeof document?require("url").pathToFileURL(__filename).href:e&&"SCRIPT"===e.tagName.toUpperCase()&&e.src||new URL("utils/frameworkDetector.cjs.js",document.baseURI).href};if(n.env?.DEV)return{name:"vite",version:n.env?.VITE_VERSION,isSSR:r}}return function(){if("undefined"!=typeof window&&(window.React||window.react))return!0;if("undefined"!=typeof require)try{return!!require.resolve("react")}catch{return!1}if("undefined"!=typeof module&&module.hot)return!0;return!1}()?{name:"react",version:n(),isSSR:r}:function(){if("undefined"!=typeof window&&(window.Vue||window.vue))return!0;if("undefined"!=typeof require)try{return!!require.resolve("vue")}catch{return!1}return!1}()?{name:"vue",version:t(),isSSR:r}:{name:"vanilla",isSSR:r}}function n(){try{if("undefined"!=typeof window&&window.React?.version)return window.React.version;if("undefined"!=typeof require){return require("react").version}}catch{}}function t(){try{if("undefined"!=typeof window&&window.Vue?.version)return window.Vue.version;if("undefined"!=typeof require){return require("vue").version}}catch{}}let o=null;exports.detectFramework=r,exports.getFramework=function(){return o?{name:o,isSSR:"undefined"==typeof window}:r()},exports.setFramework=function(e){o=e};
|
|
2
|
-
//# sourceMappingURL=frameworkDetector.cjs.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"frameworkDetector.cjs.js","sources":["../../src/utils/frameworkDetector.ts"],"sourcesContent":["/**\n * Framework Detection Utility\n * Detects which framework is available in the runtime environment\n */\n\nexport type Framework = 'react' | 'vue' | 'next' | 'nuxt' | 'vite' | 'vanilla';\n\nexport interface FrameworkInfo {\n name: Framework;\n version?: string;\n isSSR: boolean;\n}\n\n/**\n * Detects the framework in the current environment\n */\nexport function detectFramework(): FrameworkInfo {\n const isSSR = typeof window === 'undefined';\n \n // Check for Next.js\n if (typeof process !== 'undefined' && process.env?.NEXT_RUNTIME) {\n return {\n name: 'next',\n version: process.env.NEXT_VERSION,\n isSSR,\n };\n }\n \n // Check for Nuxt\n if (typeof process !== 'undefined' && (process.env?.NUXT || (globalThis as any).__NUXT__)) {\n return {\n name: 'nuxt',\n version: (process.env as any).NUXT_VERSION,\n isSSR,\n };\n }\n \n // Check for Vite (development)\n if (typeof import.meta !== 'undefined') {\n const meta = import.meta as any;\n if (meta.env?.DEV) {\n return {\n name: 'vite',\n version: meta.env?.VITE_VERSION,\n isSSR,\n };\n }\n }\n \n // Check for React\n if (detectReact()) {\n return {\n name: 'react',\n version: getReactVersion(),\n isSSR,\n };\n }\n \n // Check for Vue\n if (detectVue()) {\n return {\n name: 'vue',\n version: getVueVersion(),\n isSSR,\n };\n }\n \n // Default to vanilla\n return {\n name: 'vanilla',\n isSSR,\n };\n}\n\n/**\n * Detects if React is available\n */\nfunction detectReact(): boolean {\n // Check global React\n if (typeof window !== 'undefined') {\n if ((window as any).React || (window as any).react) {\n return true;\n }\n }\n \n // Check for React in CommonJS\n if (typeof require !== 'undefined') {\n try {\n // Use a try-catch to handle module resolution errors gracefully\n const resolved = require.resolve('react');\n return !!resolved;\n } catch {\n // React not found - this is expected if React is not installed\n return false;\n }\n }\n \n // Check for React in ES modules (runtime)\n if (typeof module !== 'undefined' && (module as any).hot) {\n // Likely in a module environment that supports React\n return true;\n }\n \n return false;\n}\n\n/**\n * Gets React version if available\n */\nfunction getReactVersion(): string | undefined {\n try {\n if (typeof window !== 'undefined' && (window as any).React?.version) {\n return (window as any).React.version;\n }\n \n if (typeof require !== 'undefined') {\n const react = require('react');\n return react.version;\n }\n } catch {\n // Version not available\n }\n \n return undefined;\n}\n\n/**\n * Detects if Vue is available\n */\nfunction detectVue(): boolean {\n // Check global Vue\n if (typeof window !== 'undefined') {\n if ((window as any).Vue || (window as any).vue) {\n return true;\n }\n }\n \n // Check for Vue in CommonJS\n if (typeof require !== 'undefined') {\n try {\n // Use a try-catch to handle module resolution errors gracefully\n const resolved = require.resolve('vue');\n return !!resolved;\n } catch {\n // Vue not found - this is expected if Vue is not installed\n return false;\n }\n }\n \n return false;\n}\n\n/**\n * Gets Vue version if available\n */\nfunction getVueVersion(): string | undefined {\n try {\n if (typeof window !== 'undefined' && (window as any).Vue?.version) {\n return (window as any).Vue.version;\n }\n \n if (typeof require !== 'undefined') {\n const vue = require('vue');\n return vue.version;\n }\n } catch {\n // Version not available\n }\n \n return undefined;\n}\n\n/**\n * Forces a specific framework (useful for testing or explicit configuration)\n */\nlet forcedFramework: Framework | null = null;\n\nexport function setFramework(framework: Framework): void {\n forcedFramework = framework;\n}\n\nexport function getFramework(): FrameworkInfo {\n if (forcedFramework) {\n return {\n name: forcedFramework,\n isSSR: typeof window === 'undefined',\n };\n }\n return detectFramework();\n}\n"],"names":["detectFramework","isSSR","window","process","env","NEXT_RUNTIME","name","version","NEXT_VERSION","NUXT","globalThis","__NUXT__","NUXT_VERSION","url","document","require","pathToFileURL","__filename","href","_documentCurrentScript","tagName","toUpperCase","src","URL","baseURI","meta","DEV","VITE_VERSION","React","react","module","hot","detectReact","getReactVersion","Vue","vue","detectVue","getVueVersion","forcedFramework","framework"],"mappings":"oSAgBO,SAASA,IACd,MAAMC,EAA0B,oBAAXC,OAGrB,GAAuB,oBAAZC,SAA2BA,QAAQC,KAAKC,aACjD,MAAO,CACLC,KAAM,OACNC,QAASJ,QAAQC,IAAII,aACrBP,SAKJ,GAAuB,oBAAZE,UAA4BA,QAAQC,KAAKK,MAASC,WAAmBC,UAC9E,MAAO,CACLL,KAAM,OACNC,QAAUJ,QAAQC,IAAYQ,aAC9BX,SAKJ,QAA2B,IAAhB,CAAAY,IAAA,oBAAAC,SAAAC,QAAA,OAAAC,cAAAC,YAAAC,KAAAC,GAAA,WAAAA,EAAAC,QAAAC,eAAAF,EAAAG,KAAA,IAAAC,IAAA,iCAAAT,SAAAU,SAAAN,MAA6B,CACtC,MAAMO,EAAO,CAAAZ,IAAA,oBAAAC,SAAAC,QAAA,OAAAC,cAAAC,YAAAC,KAAAC,GAAA,WAAAA,EAAAC,QAAAC,eAAAF,EAAAG,KAAA,IAAAC,IAAA,iCAAAT,SAAAU,SAAAN,MACb,GAAIO,EAAKrB,KAAKsB,IACZ,MAAO,CACLpB,KAAM,OACNC,QAASkB,EAAKrB,KAAKuB,aACnB1B,QAGN,CAGA,OA2BF,WAEE,GAAsB,oBAAXC,SACJA,OAAe0B,OAAU1B,OAAe2B,OAC3C,OAAO,EAKX,GAAuB,oBAAZd,QACT,IAGE,QADiBA,gBAAgB,QAEnC,CAAA,MAEE,OAAO,CACT,CAIF,GAAsB,oBAAXe,QAA2BA,OAAeC,IAEnD,OAAO,EAGT,OAAO,CACT,CAtDMC,GACK,CACL1B,KAAM,QACNC,QAAS0B,IACThC,SA2EN,WAEE,GAAsB,oBAAXC,SACJA,OAAegC,KAAQhC,OAAeiC,KACzC,OAAO,EAKX,GAAuB,oBAAZpB,QACT,IAGE,QADiBA,gBAAgB,MAEnC,CAAA,MAEE,OAAO,CACT,CAGF,OAAO,CACT,CA3FMqB,GACK,CACL9B,KAAM,MACNC,QAAS8B,IACTpC,SAKG,CACLK,KAAM,UACNL,QAEJ,CAqCA,SAASgC,IACP,IACE,GAAsB,oBAAX/B,QAA2BA,OAAe0B,OAAOrB,QAC1D,OAAQL,OAAe0B,MAAMrB,QAG/B,GAAuB,oBAAZQ,QAAyB,CAElC,OADcA,QAAQ,SACTR,OACf,CACF,CAAA,MAEA,CAGF,CA+BA,SAAS8B,IACP,IACE,GAAsB,oBAAXnC,QAA2BA,OAAegC,KAAK3B,QACxD,OAAQL,OAAegC,IAAI3B,QAG7B,GAAuB,oBAAZQ,QAAyB,CAElC,OADYA,QAAQ,OACTR,OACb,CACF,CAAA,MAEA,CAGF,CAKA,IAAI+B,EAAoC,oDAMjC,WACL,OAAIA,EACK,CACLhC,KAAMgC,EACNrC,MAAyB,oBAAXC,QAGXF,GACT,uBAZO,SAAsBuC,GAC3BD,EAAkBC,CACpB"}
|
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
function detectFramework() {
|
|
2
|
-
const isSSR = typeof window === "undefined";
|
|
3
|
-
if (typeof process !== "undefined" && process.env?.NEXT_RUNTIME) {
|
|
4
|
-
return {
|
|
5
|
-
name: "next",
|
|
6
|
-
version: process.env.NEXT_VERSION,
|
|
7
|
-
isSSR
|
|
8
|
-
};
|
|
9
|
-
}
|
|
10
|
-
if (typeof process !== "undefined" && (process.env?.NUXT || globalThis.__NUXT__)) {
|
|
11
|
-
return {
|
|
12
|
-
name: "nuxt",
|
|
13
|
-
version: process.env.NUXT_VERSION,
|
|
14
|
-
isSSR
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
if (typeof import.meta !== "undefined") {
|
|
18
|
-
const meta = import.meta;
|
|
19
|
-
if (meta.env?.DEV) {
|
|
20
|
-
return {
|
|
21
|
-
name: "vite",
|
|
22
|
-
version: meta.env?.VITE_VERSION,
|
|
23
|
-
isSSR
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
if (detectReact()) {
|
|
28
|
-
return {
|
|
29
|
-
name: "react",
|
|
30
|
-
version: getReactVersion(),
|
|
31
|
-
isSSR
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
if (detectVue()) {
|
|
35
|
-
return {
|
|
36
|
-
name: "vue",
|
|
37
|
-
version: getVueVersion(),
|
|
38
|
-
isSSR
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
return {
|
|
42
|
-
name: "vanilla",
|
|
43
|
-
isSSR
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
function detectReact() {
|
|
47
|
-
if (typeof window !== "undefined") {
|
|
48
|
-
if (window.React || window.react) {
|
|
49
|
-
return true;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
if (typeof require !== "undefined") {
|
|
53
|
-
try {
|
|
54
|
-
const resolved = require.resolve("react");
|
|
55
|
-
return !!resolved;
|
|
56
|
-
} catch {
|
|
57
|
-
return false;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
if (typeof module !== "undefined" && module.hot) {
|
|
61
|
-
return true;
|
|
62
|
-
}
|
|
63
|
-
return false;
|
|
64
|
-
}
|
|
65
|
-
function getReactVersion() {
|
|
66
|
-
try {
|
|
67
|
-
if (typeof window !== "undefined" && window.React?.version) {
|
|
68
|
-
return window.React.version;
|
|
69
|
-
}
|
|
70
|
-
if (typeof require !== "undefined") {
|
|
71
|
-
const react = require("react");
|
|
72
|
-
return react.version;
|
|
73
|
-
}
|
|
74
|
-
} catch {
|
|
75
|
-
}
|
|
76
|
-
return void 0;
|
|
77
|
-
}
|
|
78
|
-
function detectVue() {
|
|
79
|
-
if (typeof window !== "undefined") {
|
|
80
|
-
if (window.Vue || window.vue) {
|
|
81
|
-
return true;
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
if (typeof require !== "undefined") {
|
|
85
|
-
try {
|
|
86
|
-
const resolved = require.resolve("vue");
|
|
87
|
-
return !!resolved;
|
|
88
|
-
} catch {
|
|
89
|
-
return false;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
return false;
|
|
93
|
-
}
|
|
94
|
-
function getVueVersion() {
|
|
95
|
-
try {
|
|
96
|
-
if (typeof window !== "undefined" && window.Vue?.version) {
|
|
97
|
-
return window.Vue.version;
|
|
98
|
-
}
|
|
99
|
-
if (typeof require !== "undefined") {
|
|
100
|
-
const vue = require("vue");
|
|
101
|
-
return vue.version;
|
|
102
|
-
}
|
|
103
|
-
} catch {
|
|
104
|
-
}
|
|
105
|
-
return void 0;
|
|
106
|
-
}
|
|
107
|
-
let forcedFramework = null;
|
|
108
|
-
function setFramework(framework) {
|
|
109
|
-
forcedFramework = framework;
|
|
110
|
-
}
|
|
111
|
-
function getFramework() {
|
|
112
|
-
if (forcedFramework) {
|
|
113
|
-
return {
|
|
114
|
-
name: forcedFramework,
|
|
115
|
-
isSSR: typeof window === "undefined"
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
return detectFramework();
|
|
119
|
-
}
|
|
120
|
-
export {
|
|
121
|
-
detectFramework,
|
|
122
|
-
getFramework,
|
|
123
|
-
setFramework
|
|
124
|
-
};
|
|
125
|
-
//# sourceMappingURL=frameworkDetector.esm.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"frameworkDetector.esm.js","sources":["../../src/utils/frameworkDetector.ts"],"sourcesContent":["/**\n * Framework Detection Utility\n * Detects which framework is available in the runtime environment\n */\n\nexport type Framework = 'react' | 'vue' | 'next' | 'nuxt' | 'vite' | 'vanilla';\n\nexport interface FrameworkInfo {\n name: Framework;\n version?: string;\n isSSR: boolean;\n}\n\n/**\n * Detects the framework in the current environment\n */\nexport function detectFramework(): FrameworkInfo {\n const isSSR = typeof window === 'undefined';\n \n // Check for Next.js\n if (typeof process !== 'undefined' && process.env?.NEXT_RUNTIME) {\n return {\n name: 'next',\n version: process.env.NEXT_VERSION,\n isSSR,\n };\n }\n \n // Check for Nuxt\n if (typeof process !== 'undefined' && (process.env?.NUXT || (globalThis as any).__NUXT__)) {\n return {\n name: 'nuxt',\n version: (process.env as any).NUXT_VERSION,\n isSSR,\n };\n }\n \n // Check for Vite (development)\n if (typeof import.meta !== 'undefined') {\n const meta = import.meta as any;\n if (meta.env?.DEV) {\n return {\n name: 'vite',\n version: meta.env?.VITE_VERSION,\n isSSR,\n };\n }\n }\n \n // Check for React\n if (detectReact()) {\n return {\n name: 'react',\n version: getReactVersion(),\n isSSR,\n };\n }\n \n // Check for Vue\n if (detectVue()) {\n return {\n name: 'vue',\n version: getVueVersion(),\n isSSR,\n };\n }\n \n // Default to vanilla\n return {\n name: 'vanilla',\n isSSR,\n };\n}\n\n/**\n * Detects if React is available\n */\nfunction detectReact(): boolean {\n // Check global React\n if (typeof window !== 'undefined') {\n if ((window as any).React || (window as any).react) {\n return true;\n }\n }\n \n // Check for React in CommonJS\n if (typeof require !== 'undefined') {\n try {\n // Use a try-catch to handle module resolution errors gracefully\n const resolved = require.resolve('react');\n return !!resolved;\n } catch {\n // React not found - this is expected if React is not installed\n return false;\n }\n }\n \n // Check for React in ES modules (runtime)\n if (typeof module !== 'undefined' && (module as any).hot) {\n // Likely in a module environment that supports React\n return true;\n }\n \n return false;\n}\n\n/**\n * Gets React version if available\n */\nfunction getReactVersion(): string | undefined {\n try {\n if (typeof window !== 'undefined' && (window as any).React?.version) {\n return (window as any).React.version;\n }\n \n if (typeof require !== 'undefined') {\n const react = require('react');\n return react.version;\n }\n } catch {\n // Version not available\n }\n \n return undefined;\n}\n\n/**\n * Detects if Vue is available\n */\nfunction detectVue(): boolean {\n // Check global Vue\n if (typeof window !== 'undefined') {\n if ((window as any).Vue || (window as any).vue) {\n return true;\n }\n }\n \n // Check for Vue in CommonJS\n if (typeof require !== 'undefined') {\n try {\n // Use a try-catch to handle module resolution errors gracefully\n const resolved = require.resolve('vue');\n return !!resolved;\n } catch {\n // Vue not found - this is expected if Vue is not installed\n return false;\n }\n }\n \n return false;\n}\n\n/**\n * Gets Vue version if available\n */\nfunction getVueVersion(): string | undefined {\n try {\n if (typeof window !== 'undefined' && (window as any).Vue?.version) {\n return (window as any).Vue.version;\n }\n \n if (typeof require !== 'undefined') {\n const vue = require('vue');\n return vue.version;\n }\n } catch {\n // Version not available\n }\n \n return undefined;\n}\n\n/**\n * Forces a specific framework (useful for testing or explicit configuration)\n */\nlet forcedFramework: Framework | null = null;\n\nexport function setFramework(framework: Framework): void {\n forcedFramework = framework;\n}\n\nexport function getFramework(): FrameworkInfo {\n if (forcedFramework) {\n return {\n name: forcedFramework,\n isSSR: typeof window === 'undefined',\n };\n }\n return detectFramework();\n}\n"],"names":[],"mappings":"AAgBO,SAAS,kBAAiC;AAC/C,QAAM,QAAQ,OAAO,WAAW;AAGhC,MAAI,OAAO,YAAY,eAAe,QAAQ,KAAK,cAAc;AAC/D,WAAO;AAAA,MACL,MAAM;AAAA,MACN,SAAS,QAAQ,IAAI;AAAA,MACrB;AAAA,IAAA;AAAA,EAEJ;AAGA,MAAI,OAAO,YAAY,gBAAgB,QAAQ,KAAK,QAAS,WAAmB,WAAW;AACzF,WAAO;AAAA,MACL,MAAM;AAAA,MACN,SAAU,QAAQ,IAAY;AAAA,MAC9B;AAAA,IAAA;AAAA,EAEJ;AAGA,MAAI,OAAO,gBAAgB,aAAa;AACtC,UAAM,OAAO;AACb,QAAI,KAAK,KAAK,KAAK;AACjB,aAAO;AAAA,QACL,MAAM;AAAA,QACN,SAAS,KAAK,KAAK;AAAA,QACnB;AAAA,MAAA;AAAA,IAEJ;AAAA,EACF;AAGA,MAAI,eAAe;AACjB,WAAO;AAAA,MACL,MAAM;AAAA,MACN,SAAS,gBAAA;AAAA,MACT;AAAA,IAAA;AAAA,EAEJ;AAGA,MAAI,aAAa;AACf,WAAO;AAAA,MACL,MAAM;AAAA,MACN,SAAS,cAAA;AAAA,MACT;AAAA,IAAA;AAAA,EAEJ;AAGA,SAAO;AAAA,IACL,MAAM;AAAA,IACN;AAAA,EAAA;AAEJ;AAKA,SAAS,cAAuB;AAE9B,MAAI,OAAO,WAAW,aAAa;AACjC,QAAK,OAAe,SAAU,OAAe,OAAO;AAClD,aAAO;AAAA,IACT;AAAA,EACF;AAGA,MAAI,OAAO,YAAY,aAAa;AAClC,QAAI;AAEF,YAAM,WAAW,gBAAgB,OAAO;AACxC,aAAO,CAAC,CAAC;AAAA,IACX,QAAQ;AAEN,aAAO;AAAA,IACT;AAAA,EACF;AAGA,MAAI,OAAO,WAAW,eAAgB,OAAe,KAAK;AAExD,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAKA,SAAS,kBAAsC;AAC7C,MAAI;AACF,QAAI,OAAO,WAAW,eAAgB,OAAe,OAAO,SAAS;AACnE,aAAQ,OAAe,MAAM;AAAA,IAC/B;AAEA,QAAI,OAAO,YAAY,aAAa;AAClC,YAAM,QAAQ,QAAQ,OAAO;AAC7B,aAAO,MAAM;AAAA,IACf;AAAA,EACF,QAAQ;AAAA,EAER;AAEA,SAAO;AACT;AAKA,SAAS,YAAqB;AAE5B,MAAI,OAAO,WAAW,aAAa;AACjC,QAAK,OAAe,OAAQ,OAAe,KAAK;AAC9C,aAAO;AAAA,IACT;AAAA,EACF;AAGA,MAAI,OAAO,YAAY,aAAa;AAClC,QAAI;AAEF,YAAM,WAAW,gBAAgB,KAAK;AACtC,aAAO,CAAC,CAAC;AAAA,IACX,QAAQ;AAEN,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;AAKA,SAAS,gBAAoC;AAC3C,MAAI;AACF,QAAI,OAAO,WAAW,eAAgB,OAAe,KAAK,SAAS;AACjE,aAAQ,OAAe,IAAI;AAAA,IAC7B;AAEA,QAAI,OAAO,YAAY,aAAa;AAClC,YAAM,MAAM,QAAQ,KAAK;AACzB,aAAO,IAAI;AAAA,IACb;AAAA,EACF,QAAQ;AAAA,EAER;AAEA,SAAO;AACT;AAKA,IAAI,kBAAoC;AAEjC,SAAS,aAAa,WAA4B;AACvD,oBAAkB;AACpB;AAEO,SAAS,eAA8B;AAC5C,MAAI,iBAAiB;AACnB,WAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO,OAAO,WAAW;AAAA,IAAA;AAAA,EAE7B;AACA,SAAO,gBAAA;AACT;"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
"use strict";let e;function t(t,r){const o="undefined"!=typeof window?(e||(e=require("dompurify")),e):(e||(e=require("isomorphic-dompurify")),e),a={ALLOWED_TAGS:["a","b","strong","i","em","u","br","p","span"],ALLOWED_ATTR:["href","target","rel"],ALLOW_DATA_ATTR:!1,...r?.allowedTags&&{ALLOWED_TAGS:r.allowedTags},...r?.allowedAttributes&&{ALLOWED_ATTR:Object.keys(r.allowedAttributes).flatMap(e=>r.allowedAttributes[e])}};return o.sanitize(t,a)}function r(e){return t(e.replace(/(https?:\/\/[^\s]+)/g,'<a href="$1" target="_blank" rel="noopener noreferrer">$1</a>'),{allowedTags:["a"],allowedAttributes:{a:["href","target","rel"]}})}Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"}),exports.linkifyText=r,exports.safeLinkifyText=function(e){return r(e)},exports.sanitizeHtml=t;
|
|
2
|
-
//# sourceMappingURL=sanitize.cjs.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sanitize.cjs.js","sources":["../../src/utils/sanitize.ts"],"sourcesContent":["/**\n * HTML Sanitization Utilities\n * Safe HTML rendering with XSS protection\n */\n\n// Use isomorphic-dompurify for SSR compatibility\nlet DOMPurify: any;\n\n// Lazy load DOMPurify to avoid SSR issues\nfunction getDOMPurify() {\n if (typeof window !== 'undefined') {\n // Browser: use regular DOMPurify\n if (!DOMPurify) {\n DOMPurify = require('dompurify');\n }\n return DOMPurify;\n } else {\n // SSR: use isomorphic-dompurify\n if (!DOMPurify) {\n DOMPurify = require('isomorphic-dompurify');\n }\n return DOMPurify;\n }\n}\n\n/**\n * Sanitize HTML string\n * Removes dangerous scripts while preserving safe HTML\n */\nexport function sanitizeHtml(html: string, options?: {\n allowedTags?: string[];\n allowedAttributes?: Record<string, string[]>;\n}): string {\n const DOMPurifyInstance = getDOMPurify();\n \n const defaultOptions = {\n ALLOWED_TAGS: ['a', 'b', 'strong', 'i', 'em', 'u', 'br', 'p', 'span'],\n ALLOWED_ATTR: ['href', 'target', 'rel'],\n ALLOW_DATA_ATTR: false,\n };\n\n const config: any = {\n ...defaultOptions,\n ...(options?.allowedTags && { ALLOWED_TAGS: options.allowedTags }),\n ...(options?.allowedAttributes && { \n ALLOWED_ATTR: Object.keys(options.allowedAttributes).flatMap(key => \n options.allowedAttributes![key]\n )\n }),\n };\n\n return DOMPurifyInstance.sanitize(html, config);\n}\n\n/**\n * Linkify text (convert URLs to links) with sanitization\n */\nexport function linkifyText(text: string): string {\n // Simple regex to find URLs\n const urlRegex = /(https?:\\/\\/[^\\s]+)/g;\n \n // Replace URLs with anchor tags\n const linked = text.replace(\n urlRegex,\n '<a href=\"$1\" target=\"_blank\" rel=\"noopener noreferrer\">$1</a>'\n );\n\n // Sanitize the result\n return sanitizeHtml(linked, {\n allowedTags: ['a'],\n allowedAttributes: { a: ['href', 'target', 'rel'] },\n });\n}\n\n/**\n * Safe linkify for Vue v-html (alias for linkifyText)\n */\nexport function safeLinkifyText(text: string): string {\n return linkifyText(text);\n}\n\n/**\n * Sanitize plain text (remove all HTML)\n */\nexport function sanitizeText(text: string): string {\n const DOMPurifyInstance = getDOMPurify();\n return DOMPurifyInstance.sanitize(text, { ALLOWED_TAGS: [] });\n}\n"],"names":["DOMPurify","sanitizeHtml","html","options","DOMPurifyInstance","window","require","config","ALLOWED_TAGS","ALLOWED_ATTR","ALLOW_DATA_ATTR","allowedTags","allowedAttributes","Object","keys","flatMap","key","sanitize","linkifyText","text","replace","a"],"mappings":"aAMA,IAAIA,EAuBG,SAASC,EAAaC,EAAcC,GAIzC,MAAMC,EAvBgB,oBAAXC,QAEJL,IACHA,EAAYM,QAAQ,cAEfN,IAGFA,IACHA,EAAYM,QAAQ,yBAEfN,GAoBHO,EAAc,CALlBC,aAAc,CAAC,IAAK,IAAK,SAAU,IAAK,KAAM,IAAK,KAAM,IAAK,QAC9DC,aAAc,CAAC,OAAQ,SAAU,OACjCC,iBAAiB,KAKbP,GAASQ,aAAe,CAAEH,aAAcL,EAAQQ,gBAChDR,GAASS,mBAAqB,CAChCH,aAAcI,OAAOC,KAAKX,EAAQS,mBAAmBG,QAAQC,GAC3Db,EAAQS,kBAAmBI,MAKjC,OAAOZ,EAAkBa,SAASf,EAAMK,EAC1C,CAKO,SAASW,EAAYC,GAW1B,OAAOlB,EANQkB,EAAKC,QAHH,uBAKf,iEAI0B,CAC1BT,YAAa,CAAC,KACdC,kBAAmB,CAAES,EAAG,CAAC,OAAQ,SAAU,SAE/C,kHAKO,SAAyBF,GAC9B,OAAOD,EAAYC,EACrB"}
|