question

naum303 avatar image
naum303 asked

Create an Alexa Hosted Skill (Node.js) with Typescript

Hello,

I created a Hello World Skill as an Alexa Hosted Skill (Node.js) and tried to convert it to Typescript.

I renamed index.js to index.ts and changed the content to content here described:

https://developer.amazon.com/de-DE/docs/alexa/alexa-skills-kit-sdk-for-nodejs/develop-your-first-skill.html

In package.json I added "build": "tsc",

"scripts": {
    "build": "tsc",
    "test": "echo \"Error: no test specified\" && exit 1"
  },

I added a tsconfig.json

{
  "compilerOptions": {
    "lib": [
      "es2017"
    ],
    "target": "ES2015", 
    "module": "commonjs", 
    "outDir": "./", 
    "rootDir": "./", 
    "moduleResolution": "node", 
    "strict": true,
    "noUnusedLocals": true
  },
  "include": [
    "./**/*"
  ],
  "exclude": [
    "node_modules"
  ]
}

But when I try to test it, I get the following error:

"errorType": "Runtime.HandlerNotFound",
    "errorMessage": "index.handler is undefined or not exported",
    "stack": [
        "Runtime.HandlerNotFound: index.handler is undefined or not exported",
        "    at Object.module.exports.load (/var/runtime/UserFunction.js:144:11)",
        "    at Object.<anonymous> (/var/runtime/index.js:45:30)",
        "    at Module._compile (internal/modules/cjs/loader.js:778:30)",
        "    at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)",
        "    at Module.load (internal/modules/cjs/loader.js:653:32)",
        "    at tryModuleLoad (internal/modules/cjs/loader.js:593:12)",
        "    at Function.Module._load (internal/modules/cjs/loader.js:585:3)",
        "    at Function.Module.runMain (internal/modules/cjs/loader.js:831:12)",
        "    at startup (internal/bootstrap/node.js:283:19)",
        "    at bootstrapNodeJSCore (internal/bootstrap/node.js:623:3)"
    ]


What is my problem, can you please help me.

alexa
10 |5000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Anand@Amazon avatar image
Anand@Amazon answered

Hello there,

Can you add "index.ts" value to "main" parameter in package.json and try again?

10 |5000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

naum303 avatar image
naum303 answered

Hello,

I tried it, but the errors remains...

Here is my package.json

{
  "name": "hello-world",
  "version": "1.1.0",
  "description": "typescript test",
  "main": "index.ts",
  "scripts": {
    "build": "tsc",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "someone",
  "license": "None",
  "dependencies": {
    "ask-sdk-core": "^2.6.0",
    "ask-sdk-model": "^1.18.0",
    "aws-sdk": "^2.326.0",
    "typescript": "^3.7.5"
  }
}

Must the "name"-Parameter match to something from Alexa, for example the skill name?

3 comments
10 |5000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Hey there,

Please remember to export handler module in your lambda code which will be entry point in your backend code.

Also make changes to config file under .ask folder. Add "index.handler" to "handler" parameter if your backend code file name is index. It should always be <file-name>.handler.

0 Likes 0 ·

I have exported handler correctly from index. This error still occurs.

0 Likes 0 ·

Hey @Akshay Zade

Can you share more details like error message which will help us in finding the root cause?

0 Likes 0 ·
newuser-a9d8bebb-2301-4d31-934e-c11b0866b65b avatar image
newuser-a9d8bebb-2301-4d31-934e-c11b0866b65b answered

Hi @naum303!

I have past the last two week on the same issue of yours. I don't know if I have done the "right way", but I'll share my experience on setup Typescript over Alexas' Hosted Skill.


## Setup

First, I setup a new Node.js project w/ ask cli `ask new`;


## Typescript

Then, inside `/lambda` folder, I have initialized typescript w/ `tsc init`.

Just a few observation.

  • I personaly hate to mix source forder w/ dist folder because you can transform your project in a hell experience very easy, so I created a `/lambda/src` and `/lambda/dist` folders;
  • Then I have learned that Alexa's Hosted Skill does not understrand Typescript, so just to rename `index.js` to `index.ts` like Alexas' Docs suggest does not work;
  • The lambda folder requires an entrypoint file on base `lambda/index.js` folder to work properly, and this file should export the handler function. I have tried several exemples on git hub to change the default path of application startup on `skill.json`, `ask-resources.json` and `ask-states.json`. All suggested ideas does not work properly. So I have surrendered to Ask and created a dummy `index.js` file that reads `./dist/index.handler`;


### tsconfig.json

{
  "compilerOptions": {
    "target": "ES2015",
    "module": "commonjs",
    "lib": ["DOM", "ESNext"],
    "sourceMap": true,
    "outDir": "./dist",
    "rootDir": "./src",
    "composite": true,
    "strict": true, 
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  },
  "include": [
    "src/**/*"
  ],
  "exclude": [
    "node_modules",
    "**/*.spec.ts"
  ]
}


### `lambda/index.js`

var skill = require('./dist/index');
exports.handler = skill.handler;


## Deploy

The other problem is How can I run typescript compilation when Ask runs deploy? On Alexas' Hosted Skill you don't have access to deploy pipelines. After several workarounds I realized that Ask pipeline runs `npm install --production`, so I was able to enqueue npm scripts on install pipelines and it was exactly what I have done. I created a build script and enqueued it on `postinstall: ""` event.

Because nothing is easy on the Alexas' world, the Hosted Skill take a few more days of my life w/ very unusual side effects. Some times when I publish a new version by running `git push origin master`, the Ask UI tells us that it is deploying but my changes was not fully uploaded on aws lambdas.... Because of that I have learned that I always have to increase `package.json` version to fully update lambdas...

Other unnusual thing is that sometimes I fell like typescript does not transpile new versions... so I updated my pipeline scripts to always remove dist folder before build.

Finally, because Ask pipeline always runs npm install w/ --production flag, you can't have dependencies on devDependencies....


### package.json

{
  "name": "---",
  "version": "0.1.6",
  "description": "---",
  "main": "index.js",
  "scripts": {
    "clean": "npx rimraf ./dist ./tsconfig.tsbuildinfo",
    "postinstall": "npm run clean && npm run build",
    "build": "npx tsc",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "dependencies": {
    "ask-sdk-core": "^2.6.0",
    "ask-sdk-model": "^1.18.0",
    "aws-sdk": "^2.326.0",
    "typescript": "^4.1.2",
    "rimraf": "^3.0.0"
  },
  "devDependencies": {}
}
10 |5000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.