Skip to content

Commit

Permalink
feat: Convert to ESM (#1699) v11 release
Browse files Browse the repository at this point in the history
feat: Convert to ESM v11 release
chore: improve logging when generating a Hubot

BREAKING CHANGE: v11 release
BREAKING CHANGE: Convert to ESM
  • Loading branch information
joeyguerra committed Nov 12, 2023
1 parent 7fa3841 commit 31639b3
Show file tree
Hide file tree
Showing 46 changed files with 328 additions and 513 deletions.
5 changes: 2 additions & 3 deletions README.md
Expand Up @@ -6,9 +6,8 @@

# Hubot

**Note: v10.0.4 contains the removal of CoffeeScript**

Semver is looking for **BREAKING CHANGE** singular, not **BREAKING CHANGES**. As a result, the removal of CoffeeScript was marked as the `v10.0.4` release.
**Note: v10.0.4 accidentaly contains the removal of CoffeeScript; v10.0.5 puts it back in**
**Note: v11 removes CoffeeScript and converts this codebase to ESM**

Hubot is a framework to build chat bots, modeled after GitHub's Campfire bot of the same name, hubot.
He's pretty cool. He's [extendable with scripts](https://hubotio.github.io/hubot/docs#scripts) and can work
Expand Down
36 changes: 14 additions & 22 deletions bin/hubot.js → bin/Hubot.mjs
@@ -1,15 +1,13 @@
'use strict'

const fs = require('fs')
const pathResolve = require('path').resolve

const OptParse = require('../src/OptParse.js')

const Hubot = require('..')
const create = require('../src/GenHubot.js')
import fs from 'node:fs'
import { resolve as pathResolve } from 'node:path'
import OptParse from '../src/OptParse.mjs'
import Hubot from '../index.mjs'
import create from '../src/GenHubot.mjs'

const switches = [
['-a', '--adapter HUBOT_ADAPTER', 'The Adapter to use, e.g. "shell" (to load the default hubot shell adapter)'],
['-a', '--adapter HUBOT_ADAPTER', 'The Adapter to use, e.g. "Shell" (to load the default hubot Shell adapter)'],
['-f', '--file HUBOT_FILE', 'Path to adapter file, e.g. "./adapters/CustomAdapter.mjs"'],
['-c', '--create HUBOT_CREATE', 'Create a deployable hubot'],
['-d', '--disable-httpd HUBOT_HTTPD', 'Disable the HTTP server'],
Expand Down Expand Up @@ -97,13 +95,13 @@ if (options.file) {
}

const robot = Hubot.loadBot(options.adapter, options.enableHttpd, options.name, options.alias)
module.exports = robot
export default robot

async function loadScripts () {
await robot.load(pathResolve('.', 'scripts'))
await robot.load(pathResolve('.', 'src', 'scripts'))

loadExternalScripts()
await loadExternalScripts()

const tasks = options.scripts.map((scriptPath) => {
if (scriptPath[0] === '/') {
Expand All @@ -115,25 +113,19 @@ async function loadScripts () {
await Promise.all(tasks)
}

function loadExternalScripts () {
async function loadExternalScripts () {
const externalScripts = pathResolve('.', 'external-scripts.json')

if (!fs.existsSync(externalScripts)) {
return
}

fs.readFile(externalScripts, function (error, data) {
if (error) {
throw error
}

try {
const data = await fs.promises.readFile(externalScripts)
try {
robot.loadExternalScripts(JSON.parse(data))
} catch (error) {
console.error(`Error parsing JSON data from external-scripts.json: ${error}`)
process.exit(1)
}
})
} catch (e) {
robot.logger.info('No external-scripts.json found. Skipping.')
}
}

(async () => {
Expand Down
18 changes: 8 additions & 10 deletions bin/e2e-test.sh
Expand Up @@ -9,22 +9,20 @@ trap "{ CODE=$?; popd; rm -rf $TEMP_ROOT; exit $CODE; }" EXIT
## https://github.com/hubotio/hubot/blob/main/docs/index.md

## use this hubot version
echo "$ create hubot in $TEMP_ROOT"
echo "$ install Hubot from $HUBOT_FOLDER"
echo "Creating hubot in $TEMP_ROOT"
echo " and installing Hubot from $HUBOT_FOLDER"
npm init -y
npm i $HUBOT_FOLDER coffeescript
npm i $HUBOT_FOLDER

./node_modules/.bin/hubot --create myhubot
cd myhubot
export HUBOT_INSTALLATION_PATH=$HUBOT_FOLDER
./node_modules/.bin/hubot --create .

# npm install /path/to/hubot will create a symlink in npm 5+ (http://blog.npmjs.org/post/161081169345/v500).
# As the require calls for app-specific scripts happen inside hubot, we have to
# set NODE_PATH to the app’s node_modules path so they can be found
echo "$ Update NODE_PATH=$TEMP_ROOT/node_modules so everything can be found correctly."
export NODE_PATH=$TEMP_ROOT/node_modules:$TEMP_ROOT/myhubot/node_modules
export PATH=$PATH:$TEMP_ROOT/node_modules/.bin:$TEMP_ROOT/myhubot/node_modules/.bin
export HUBOT_INSTALLATION_PATH=$HUBOT_FOLDER
echo $HUBOT_INSTALLATION_PATH
export NODE_PATH=$TEMP_ROOT/node_modules
export PATH=$PATH:$TEMP_ROOT/node_modules/.bin

## start, but have to sleep 1 second to wait for hubot to start and the scripts to load
expect <<EOL
Expand All @@ -39,7 +37,7 @@ expect <<EOL
}
send "e2etest adapter\r"
expect {
"shell" {}
"Shell" {}
timeout {exit 1}
}
EOL
10 changes: 2 additions & 8 deletions bin/hubot
@@ -1,9 +1,3 @@
#!/usr/bin/env coffee
#!/usr/bin/env node

# While all other files have been converted to JavaScript via https://github.com/github/hubot/pull/1347,
# we left the `bin/hubot` file to remain in CoffeeScript in order prevent
# breaking existing 3rd party adapters of which some are still written in
# CoffeeScript themselves. We will deprecate and eventually remove this file
# in a future version of hubot

require './hubot.js'
import('./Hubot.mjs').then(async ({ default: robot }) => {})
4 changes: 2 additions & 2 deletions docs/adapters/campfire.md
Expand Up @@ -14,11 +14,11 @@ You will need a Campfire account to start.

Next, you will need to create a user on your Campfire account for your Hubot, then give it access so it can join to your rooms. You will need to create a room if you haven't already.

Hubot defaults to using its [shell](./shell.html), so to use Campfire instead, you can run hubot with `-a campfire`:
Hubot defaults to using its [Shell](./shell.html), so to use Campfire instead, you can run hubot with `-a Campfire`:

% bin/hubot -a campfire

If you are deploying to Heroku or using foreman, you need to make sure the hubot is called with `-a campfire` in the `Procfile`:
If you are deploying to Heroku or using foreman, you need to make sure the hubot is called with `-a Campfire` in the `Procfile`:

web: bin/hubot -a campfire -n Hubot

Expand Down
16 changes: 4 additions & 12 deletions docs/adapters/development.md
Expand Up @@ -8,12 +8,10 @@ permalink: /adapters/development.html

## Adapter Basics

All adapters inherit from the Adapter class in the `src/adapter.js` file.

If you're writing your adapter in ES2015, you must require the ES2015 entrypoint instead:
All adapters inherit from the Adapter class in the `src/Adapter.mjs` file.

```javascript
const Adapter = require('hubot/es2015').Adapter;
const Adapter = require('hubot/index.mjs').Adapter;
```

There are certain methods that you will want to override. Here is a basic stub of what an extended Adapter class would look like:
Expand Down Expand Up @@ -60,10 +58,7 @@ exports.use = (robot) => new Sample(robot)
"dependencies": {
},
"peerDependencies": {
"hubot": ">=3.0"
},
"devDependencies": {
"coffeescript": ">=1.2.0"
"hubot": ">=11"
}
```

Expand Down Expand Up @@ -117,10 +112,7 @@ Another option is to load the file from local disk.
"dependencies": {
},
"peerDependencies": {
"hubot": ">=9"
},
"devDependencies": {
"coffeescript": ">=2.7.0"
"hubot": ">=11"
}
```

Expand Down
4 changes: 2 additions & 2 deletions docs/adapters/shell.md
Expand Up @@ -11,8 +11,8 @@ It can be useful for testing scripts before using them on a live hubot.

## Getting Started

To use the shell adapter you can simply omit the `-a` option when running
hubot as it will use the shell adapter by default.
To use the Shell adapter you can simply omit the `-a` option when running
hubot as it will use the Shell adapter by default.

% bin/hubot

Expand Down
7 changes: 3 additions & 4 deletions docs/deploying/azure.md
Expand Up @@ -37,13 +37,12 @@ First, run the follow command to add `deploy.cmd` to your hubot directory. This

Then, edit this file and look for the sections that give you steps 1, 2 and 3. You're going to add a 4th step:

:: 4. Create Hubot file with a coffee extension
copy /Y "%DEPLOYMENT_TARGET%\node_modules\hubot\bin\hubot" "%DEPLOYMENT_TARGET%\node_modules\hubot\bin\hubot.coffee"
:: 4. Create Hubot file with a js extension
copy /Y "%DEPLOYMENT_TARGET%\node_modules\hubot\bin\hubot" "%DEPLOYMENT_TARGET%\node_modules\hubot\bin\Hubot.mjs"

Now, create a new file in the base directory of hubot called `server.js` and put these two lines into it:

require('coffeescript/register');
module.exports = require('hubot/bin/hubot.coffee');
module.exports = await import('hubot/bin/Hubot.mjs');

Finally you will need to add the environment variables to the website to make sure it runs properly. You can either do it through the GUI (under configuration) or you can use the Azure PowerShell command line, as follows (example is showing slack as an adapter and mynewhubot as the website name).

Expand Down
4 changes: 2 additions & 2 deletions docs/docs.md
Expand Up @@ -25,7 +25,7 @@ Now open `package.json` in your code editor and add a `start` property to the `s
}
```

Start your Hubot instance by executing `npm start`. It will start with the built in [shell adapter](/adapters/shell.html), which starts a [REPL](https://en.wikipedia.org/wiki/Read–eval–print_loop) where you can type commands.
Start your Hubot instance by executing `npm start`. It will start with the built in [Shell adapter](/adapters/shell.html), which starts a [REPL](https://en.wikipedia.org/wiki/Read–eval–print_loop) where you can type commands.

Your terminal should look like:

Expand All @@ -39,7 +39,7 @@ Typing `help` will list some default commands that Hubot's default adapter, Shel
Hubot> help
usage:
history
exit, \q - close shell and exit
exit, \q - close Shell and exit
help, \? - print this usage
clear, \c - clear the terminal screen
Hubot>
Expand Down
31 changes: 0 additions & 31 deletions es2015.js

This file was deleted.

40 changes: 0 additions & 40 deletions index.js

This file was deleted.

52 changes: 52 additions & 0 deletions index.mjs
@@ -0,0 +1,52 @@
'use strict'

import User from './src/User.mjs'
import Brain from './src/Brain.mjs'
import Robot from './src/Robot.mjs'
import Adapter from './src/Adapter.mjs'
import Response from './src/Response.mjs'
import Middleware from './src/Middleware.mjs'
import { Listener, TextListener } from './src/Listener.mjs'
import { TextMessage, EnterMessage, LeaveMessage, TopicMessage, CatchAllMessage, Message } from './src/Message.mjs'
import { DataStore, DataStoreUnavailable } from './src/DataStore.mjs'

const loadBot = (adapter, enableHttpd, name, alias) => new Robot(adapter, enableHttpd, name, alias)
export {
Adapter,
User,
Brain,
Robot,
Response,
Listener,
TextListener,
Message,
TextMessage,
EnterMessage,
LeaveMessage,
TopicMessage,
CatchAllMessage,
DataStore,
DataStoreUnavailable,
Middleware,
loadBot
}

export default {
Adapter,
User,
Brain,
Robot,
Response,
Listener,
TextListener,
Message,
TextMessage,
EnterMessage,
LeaveMessage,
TopicMessage,
CatchAllMessage,
DataStore,
DataStoreUnavailable,
Middleware,
loadBot
}
17 changes: 2 additions & 15 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 31639b3

Please sign in to comment.