amazon-connect / amazon-connect-chatjs

Amazon Connect ChatJS - a browser-based contact center integration API for Chat on the Agent and Customer side.
https://docs.aws.amazon.com/connect/latest/adminguide/what-is-amazon-connect.html
Apache License 2.0
93 stars 53 forks source link

ReferenceError: connect is not defined in JS #170

Closed Siya-stackit closed 1 year ago

Siya-stackit commented 1 year ago

Hi experiencing this issue when i try import amazon-connect-chatjs, image

and I tried running it on npm runkit and it shows the same: image

Please assist

spencerlepine commented 1 year ago

Hi @Siya-stackit,

ChatJS support is currently for ECMAScript modules (ESM). Following our readme, you can import ChatJS into your project like so:

import "amazon-connect-chatjs";

// ...

Can you confirm if this resolves your issue? If not, please include more details about your setup (e.g. NodeJS version, using CommonJS or ESM...)


By default, runkit will not use import statement:

Screenshot 2023-05-17 at 7 37 05 AM
Siya-stackit commented 1 year ago

Hi

Thank you for your reply, I am currently using Node.js v16.16.0.

So I am using ES Modules, because I have node_module folder with all the independent files.

I want to use it in a AWS lambda version 16

I am still experiencing this issue but for some reason when I install an older version which is 1.3.2 it doesn't give me this reference error which confuses me, does this version support onParticipantIdle()?

spencerlepine commented 1 year ago

Hi @Siya-stackit,

It looks like amazon-connect-chatjs@1.3.2 supports onParticipantIdle() [ref], but this wasn't added to the README until #108, which was updated in v1.3.4.

Note: if this is not a browser runtime implementation, perhaps you could look into the @aws-sdk/client-connect (which supports commonJS require imports)?

1) Can you confirm that this issue still occurs when using import "amazon-connect-chatjs" syntax in this lambda?

2) Are you using const foo = require("bar"); commonJS syntax? [Node documentation]. This is not officially supported as noted in README.

3) It could also help if you provide snippet of Lambda function code. Please let me know if you have further questions.

Thanks, Spencer

Siya-stackit commented 1 year ago
// import "amazon-connect-chatjs";
const connectChatjs = require("amazon-connect-chatjs");
const AWS = require('aws-sdk');
//const Connect = new AWS.Connect();
exports.handler = async (event) => {
    console.log(event.Details.ContactData.ContactId)
    console.log(event.Details.ContactData.InstanceARN)
    var response = await CustomerIdle(event.Details.ContactData.InstanceARN, event.Details.ContactData.ContactId);

    // const customerChatSession = connect.ChatSession.create({
    //     chatDetails: { // REQUIRED
    //         contactId: "...", // REQUIRED
    //         participantId: "...", // REQUIRED
    //         participantToken: "...", // REQUIRED
    //     },
    //     options: { // optional
    //         region: "us-east-1", // optional, defaults to `region` set in `connect.ChatSession.setGlobalConfig()`
    //     },
    //     type: connect.ChatSession.SessionTypes.CUSTOMER, // REQUIRED
    // });
    // const {
    //     connectCalled,
    //     connectSuccess
    // } =  chatSession.connect();

    connectChatjs.ChatSession.onParticipantIdle(event => {
        const {
            chatDetails,
            data
        } = event;
        if (data.ParticipantRole === "CUSTOMER") {
            // ...
            console.log("idling...")
        }
    });
};
async function CustomerIdle(InstanceARN, ContactId) {
    var params = {
        ChannelConfiguration: {
            Chat: {
                ParticipantTimerConfigList: [{
                    ParticipantRole: "CUSTOMER",
                    TimerType: "IDLE",
                    TimerValue: {
                        //ParticipantTimerAction: "Unset",
                        ParticipantTimerDurationInMinutes: 2
                    }
                }, ]
            }
        },
        ContactId: ContactId,
        InstanceId: InstanceARN
    };
    var response = await Connect.updateParticipantRoleConfig(params).promise();
    console.log("This is the response :", response);
    return response;
}

Since i am using node 16, for me to use import "amazon-connect-chatjs" It requires me to add a file package.json and add { "type":"module" } Which I tried and it results to the same issue with the latest version. is this adviseable?

spencerlepine commented 1 year ago

I have not tested a lambda function using both syntax before, but you can try this. Let me know if you have any further questions.

When you use require to import the AWS SDK, you are utilizing CommonJS syntax, which is the traditional way of importing modules in Node.js. On the other hand, when you use import "amazon-connect-chatjs", you are using ECMAScript Modules (ESM) syntax.

By default, Node.js treats each JavaScript file as either CommonJS or ESM. However, starting with Node.js 12.x, there is experimental support for using both syntaxes in the same file.

Since you are using Node 16, this should work - you can still use require even if you have added "type": "module" to your package.json file.

When you add "type": "module" to your package.json, it enables ECMAScript Modules (ESM) syntax for your JavaScript files. This means you can use import and export statements to import and export modules.

However, Node.js also supports backward compatibility with CommonJS modules (using require and module.exports syntax) even when using ESM. You can continue using require to import CommonJS modules alongside import for ECMAScript Modules.

Siya-stackit commented 1 year ago

Hi @spencerlepine,

Thank you for your reply :)

in both scenarios which I have attempted it brings me back to this issue I started on the first message on this thread.

spencerlepine commented 1 year ago

🔴 Ignore this comment, this will not be supported in Lambda

To clarify, this exact setup is resulting in ReferenceError: connect is not defined error?

// app.js

import "amazon-connect-chatjs";

// ...
// package.json
{
  "name": "your-lambda-function",
  "version": "1.0.0",
  "type": "module",
  "dependencies": {
    // dependencies
  }
}
spencerlepine commented 1 year ago

Taking another look, when importing amazon-connect-chatjs into your Lambda function using Node.js 16 with ESM (ECMAScript Modules) syntax, it could be due to the module not correctly exposing the necessary global variable in the ESM environment.

ChatJS needs to set connect in the window or global object, which does not happen in the Lambda.

perhaps you could look into the @aws-sdk/client-connectparticipant (which supports commonJS require imports)?

In a Lambda function running in the Node.js environment, there is no window object (which represents the global object in a browser environment) or a global object (which represents the global object in Node.js).

If the amazon-connect-chatjs module relies on the window or global object being present to set its exports or define global variables, it might not work as expected in a Lambda function.

spencerlepine commented 1 year ago

Update:

ChatJS is intended to be a low-level abstraction for ParticipantService API, this will not work for this use case (since ChatJS does not officially support CommonJS require)

Linking the @aws-sdk/client-connectparticipant library - which is lower-level sdk for Amazon Connect Participant Service.

const { ConnectParticipantClient, SendMessageCommand } = require("@aws-sdk/client-connectparticipant");

exports.handler = async (event) => {
  // Extract necessary information from the event
  const { contactId, participantId, message } = event;

  // Create an instance of the ConnectParticipantClient
  const client = new ConnectParticipantClient({ region: "REGION" });

  try {
    // Prepare the input parameters for the SendMessageCommand
    const params = {
      ConnectionToken: participantId,
      Content: message,
      ContentType: "text/plain",
      Type: "MESSAGE",
    };

    // Create an instance of the SendMessageCommand
    const command = new SendMessageCommand(params);

    // Send the message using the client
    const response = await client.send(command);

    // Log the response from the service
    console.log(response);

    return {
      statusCode: 200,
      body: "Message sent successfully",
    };
  } catch (error) {
    console.error(error);

    return {
      statusCode: 500,
      body: "An error occurred while sending the message",
    };
  } finally {
    // Clean up the client
    client.destroy();
  }
};
Siya-stackit commented 1 year ago

Hi @spencerlepine,

Amazon Connect Participant Service, doesn't have the function that I need for my use case, I want the event when the Customer in the chat has become idle and do something when that happens:

chatSession.onParticipantIdle(event => { const { chatDetails, data } = event; if (data.ParticipantRole === "Customer") { // Do something here } });

Siya-stackit commented 1 year ago

I attempted with import "@aws-sdk/client-connect";

when I call create it gives a new reference error: image

spencerlepine commented 1 year ago

Hi @Siya-stackit ,

Can you double check that you are importing all the libraries properly according to the other packages documentation?

Examples for quick reference:

import * as AWS from "@aws-sdk/client-connectparticipant";
const client = new AWS.ConnectParticipant({ region: "REGION" });

// async/await.
try {
  const data = await client.completeAttachmentUpload(params);
  // process data.
} catch (error) {
  // error handling.
}

// Promises.
client
  .completeAttachmentUpload(params)
  .then((data) => {
    // process data.
  })
  .catch((error) => {
    // error handling.
  });

// callbacks.
client.completeAttachmentUpload(params, (err, data) => {
  // process err and data.
});

OR

import { ConnectClient } from "@aws-sdk/client-connect";

const client = new ConnectClient({
  region: "us-east-1",
});

const params = {
  InstanceId: "my-connect-instance-id",
  ContactFlowId: "my-contact-flow-id",
  DestinationPhoneNumber: "1234567890",
};

client.startOutboundVoiceContact(params, (err, data) => {
  if (err) {
    console.log(err);
  } else {
    console.log(data);
  }
});
spencerlepine commented 1 year ago

Please also refer to the ChatJS README about conflicts with the SDK when importing: https://github.com/amazon-connect/amazon-connect-chatjs#a-note-about-the-aws-sdk-and-chatjs

Note, there does not appear to be a bug with ChatJS - it appears there are difficulties importing the different SDK files. There is no further action we will take to update ChatJS since it is intended for browser support. I believe for this use case you should use @aws-sdk/client-connectparticipant / @aws-sdk/client-connect

If you have further question that the documentation is not clear about for setting up this use case, feel free to keep this thread open. Otherwise, there does not appear to be issue specific to ChatJS.

Thanks, Spencer

spencerlepine commented 1 year ago

Hi @Siya-stackit, if there are no further updates team will resolve this issue.

Please feel free to reach out and raise new issue if you face another problem, thanks!

Siya-stackit commented 1 year ago

Hi Spencer

thank you so much for the replies

take care!!!💯