Changelog History
Page 5
-
v21.0.11 Changes
January 16, 2020β‘οΈ Update type of pluginOptions to hash
-
v21.0.10 Changes
January 16, 2020π² Filter and include task arguments in task log messages (#1391)
Before
info: [worker] job success workerId=1 class=hello queue=default
After
info: [worker] job success workerId=1 class=hello queue=default args={"thing":"[FILTERED]", "id": 123}
π We use
config.general.filteredParams
, like the web server, to decide what params to filter when logged.Misc
-
v21.0.9 Changes
December 21, 2019Why Typescript?
π Actionhero has moved to Typescript.
π Typescript is a language that
compiles
to javascript that makes the developer experience much nicer. It includes features like type checking, sharing interfaces and modules, and generally other "quality of life" features found in other languages to help you write better javascript code.For Actionhero, that means we can now provide:
Type Hinting
Module definitions
π Automatic Documentation directly from the code
π Visit docs.actionherojs.com to see this live!
...and an overall more pleasant developer experience!
Note : You do not have to use Typescript to use Actionhero! Other than some layout changes to your project, you can continue to use Actionhero with regular javascript node.js projects. We will always ship compiled javascript files to NPM so that actionhero will still work with the most recent versions of Node.js. That said, the generators will favor Typescript projects moving forward, creating Typescript files
β For now, the
latest
Actionhero tag on NPM is still v20, the last javascript version of Actionhero. You can start using the Typescript version of Actionhero today by opting into thenext
tag:npm install actionhero@next ./node\_modules/.bin/actionhero generate npm install npm run dev
π¦ Actionhero will create and install everything you need for a pleasant typescript experience, including a
tsconfig
file, node's@types
and development tools already linked into yourpackage.json
β¬οΈ Upgrading Packages & Package.json
π¦ If you are upgarding an existing Actionhero project, the first thing to do is install the related packages and create new files:
npm install --save actionhero@next npm install --save-dev @types/node prettier npm uninstall standard
β‘οΈ Update your scripts in
package.json
"scripts": { "dev": "ts-node-dev --transpile-only ./node\_modules/.bin/actionhero start", "start": "actionhero start", "actionhero": "actionhero", "test": "jest", "pretest": "npm run build && npm run lint", "postinstall": "npm run build", "build": "tsc --declaration", "lint": "prettier --check src/\*/\*\* \_\_test\_\_/\*/\*\*", "pretty": "prettier --write src/\*/\*\* \_\_test\_\_/\*/\*\*"},
π¦ and your
jest
config as well, also inpackage.json
"jest": { "testEnvironment": "node", "transform": { "^.+\\.ts?$": "ts-jest" } };
β Remove the block about
standard
from yourpackage.json
. We are switching to prettier because it has better typescript support.Remember - you will be using
npm run dev
now when developing locally.π§ Typescript Configuration
Typescript is managed by a
tsconfig.json
file at the root of your project. Create one now with the following content:{ "compilerOptions": { "outDir": "./dist", "allowJs": true, "module": "commonjs", "target": "es2018" }, "include": ["./src/\*\*/\*"] }
Project Structure
- Create the
src
anddist
directories π 2. Move Actions, Tasks, Initializers, Servers, and Config intosrc
- Create a new
modules
directory
Your project should now look like this:
| |- boot.js |- src | - config | - (project settings) | | - actions | -- (your actions) | | - initializers | -- (any additional initializers you want) | | - servers | -- (custom servers you may make) | | - tasks | -- (your tasks) | | - bin | -- (your custom CLI commands) | |- locales |-- (translation files) | |- __tests__ |-- (tests for your API) | | - log |-- (default location for logs) | |- node_modules |-- (your modules, actionhero should be npm installed in here) | |- pids |-- (pidfiles for your running servers) | |- public |-- (your static assets to be served by /file) | readme.md package.json
β‘οΈ Update JS to TS syntax
π Typescript uses the latest ES6-style syntax for importing and exporting things. You do not need to use babel to get this to work... Typescript does it for you!
- Rename all the files you just moved into
src
from*.js
to*.ts
files- A Helpful rename command for unix/osx computers to do this is ->
for f in _.js; do mv -- "$f" "${f%.js}.ts"; done
- A Helpful rename command for unix/osx computers to do this is ->
- π
Change the imports from Require-style
const {thing} = require('thing')
to Import-styleimport { thing } from 'thing'
- π
Change all the exports from Module-style
module.exports = ...
orexports.thing = ...
to ES6-styleexport const thing = ...
For example:
OLD
const { Action } = require("actionhero");exports.default = class MyAction extends Action { constructor() { super(); this.name = "hello"; this.description = "an actionhero action"; this.outputExample = { message: "hello" }; } async run({ response }) { response.message = "hello"; } };
π NEW
import { Action } from "actionhero";export class MyAction extends Action { constructor() { super(); this.name = "hello"; this.description = "an actionhero action"; this.outputExample = { message: "hello" }; } async run({ response }) { response.message = "hello"; } }
Config
π§ The config module (it is a module now!) produces a static object with your configuration. This means that it can be required via
import {config} from 'actionhero'
at any point in your project's life cycle... you no longer need to wait for the initialization process to complete. However, this required some changes:- The config methods no longer provide
api
, they provideconfig
. Only other information from other config files is available to you, nothing from the rest of the application.
β¬οΈ To upgrade your config:
- π Change all of the exports, per above. When exporting the default config, use
DEFAULT
(all caps), ie:export const DEFAULT = {config: { ... }}
β‘οΈ Update your paths in
config/general
, ie:paths: { action: [path.join(__dirname, "..", "actions")], task: [path.join(__dirname, "..", "tasks")], server: [path.join(__dirname, "..", "servers")], cli: [path.join(__dirname, "..", "bin")], initializer: [path.join(__dirname, "..", "initializers")], public: [path.join(process.cwd(), "public")], pid: [path.join(process.cwd(), "pids")], log: [path.join(process.cwd(), "log")], plugin: [path.join(process.cwd(), "node_modules")], locale: [path.join(process.cwd(), "locales")], test: [path.join(process.cwd(), "__tests__")], src: path.join(process.cwd(), "src"),dist: path.join(process.cwd(), "dist")}
β Donβt forget any paths you might have in other environments (like
test
)!Middleware and Sessions
Now with Typescript, youβll get an error if you try to set arbitrary properties on the data object either within an
Action
orMiddleware
. We need a place to pass data from the middleware to the action.// in an initializerimport { action } from "actionhero";import { models } from "./../models"; // in your projectconst authenticatedTeamMemberMiddleware = { name: "authenticated-team-member", global: false, priority: 1000, preProcessor: async data =\> { const { Team, TeamMember } = models; const sessionData = await api.session.load(data.connection); if (!sessionData) { throw new Error("Please log in to continue"); } else if ( !data.params.csrfToken ||data.params.csrfToken !== sessionData.csrfToken ) { throw new Error("CSRF error"); } else { const teamMember = await TeamMember.findOne({ where: { guid: sessionData.guid }, include: Team }); data.session.data = sessionData; /// \<--- HERE/data.session.teamMember = teamMember; /// \<--- HERE/ } } };action.addMiddleware(authenticatedTeamMemberMiddleware);
Modules and Initializers
π A number of things have been moved out of the API object to simplify their use by creating import/export modules you can require directly. In this way, you can get type hinting for various parts of Actionhero! This is a logical separation between
initializers
- code that executes when your server boots up and loads or connects vsmodules
which provide an API for you to use in your code.For example, the
task
system has been split into 2 parts - both amodule
andinitializer
. The initializer continues to load your tasks intoapi.tasks.tasks
, but doesnβt expose any methods for you to use. Now, when you want to enqueue a task, you calltask.enqueue()
you load it from the module viaimport {task} from 'actionhero'
The
initialize
,start
, andstop
methods of your initializers will now be passedconfig
. This is helpful in the off chance you are modifyingconfig
and cannot rely on the static export of that information (this is rare).β Removed from the API object and are now directly exported by Actionhero as modules:
π² ie:
import { log, config } from 'actionhero'
- π log (the method to write to the logs)
- config (the config object hash)
- action (addMiddleware)
- task (addMiddleware)
- cache
- task
- i18n
- specHelper
- id (the serverβs id)
- env (development, staging, production)
- localize (method that accepts a string and a connection)
The API object
π what remains on the API object are truly things about your API - actions, tasks, servers, initializers. And now these elements are very typesafe. You can no longer add and remove things randomly to the API object. This means that in your project, you should create imports and exports directly and share them with your actions and tasks.
Polyfill
π A polyfill will be included in the first few releases of Actionhero in typescript to port the new exports back to the
api
object. A warning will be displayed.A new config setting to enable or disable the polyfill is located at
config.general.legacyApiPolyfill
Config
config.general.id
: can no longer be setconfig.i18n.determineConnectionLocale
: this method should be set on thei18n
object exported by Actionhero.
Chat
chatRoom.sanitizeMemberDetails()
is no longer overrideable/customizable.
WatchFileAndAct
π¦ We have removed the custom module loaders for Actionhero's development mode,
watchFileAndAct
. Now that we need to transpile our applications from typescript to javascript, we can rely on some of the excellent packages already developed for this purpose. Newly generated Actionhero projects will make use ofnode-ts-dev
(https://github.com/whitecolor/ts-node-dev) to boot and reload your projects when running in typescript mode.π¦ Javascript projects can do a similar thing via the nodemon (https://nodemon.io/) package
- Create the
-
v20.0.0 Changes
October 07, 2019Always prefer actionhero in node_modules
π Related to actionhero/ah-swagger-plugin#6
We have changed how Actionhero loads itself to always prefer components in
node_modules
relative to thecwd
(current working directory):Pros
- There is no change to the behavior or a normal actionhero project
- Globally installed Actionhero (
npm install -g actionhero
) is now resistant to minor version changes between projects - π Allows plugins to install a version of actionhero as a
devDependancy
, and for us to boot the project and not have conflicting paths to source actionhero from. You can now justnpm start
(./node_modules/.bin/actionhero
) in your plugins to start a server to run your plugins
Cons
- If you start actoinhero from a dameon (like
forever
) without firstcd
-ing to the proper directory first things might not work depending on your load paths. - Slightly slower boot time (as we are checking if files exist before trying to load them).
- Things (may) weird with yarn/lerna workspaces
This is a breaking change
Via #1338
β Create tests for actions and tasks when generating via CLI
Completes #1005
β When generating a new
action
ortask
via the CLI, a template test will also now be creates in__tests__
. This will help encourage better testing of your actionhero projects. Of course, you can always delete the test files if you don't want it.Adds
api.config.general.paths.test
as setting in./config/api.js
which defaults to[path.join( __dirname, '/../__ tests__')]
This is a breaking change due to the new path
Via #1332
β Add custom http status code with error object
Currently, we have to add the custom error response code like this:
data.connection.rawConnection.responseHttpCode = 404
We can use the error.code that already exists in theerror object
Now in action, you can do something like this :
const raiseNotFound = \<your-condition\>if(raiseNotFound) { const notFoundError = new Error(\<msg\>) notFoundError.code = 404throw notFoundError }
via #1334
findEnqueuedTasks
β Adds api.specHelper.findEnqueuedTasks to write tests that check that task was enqueued!
describe('task testing', () =\> { beforeEach(async () =\> { await api.resque.queue.connection.redis.flushdb() }) test('detect that a task was enqueued to run now', async () =\> { await api.tasks.enqueue('regularTask', { word: 'testing' }) const found = await api.specHelper.findEnqueuedTasks('regularTask') expect(found.length).toEqual(1) expect(found[0].args[0].word).toEqual('testing') expect(found[0].timestamp).toBeNull() }) })
via #1331
Misc
-
v19.2.2
August 19, 2019 -
v19.2.1 Changes
July 19, 2019v19.2.1
π Generated File Fixes for Satndard.js
β‘οΈ Update test example and generated initializers so that they pass Standard.js checks
by @evanthaler via 06158ad
-
v19.2.0 Changes
July 19, 2019Actionhero v19.2.0
Boot Loader for Actionhero
When creating a new Actionhero project, there is a now a top-level
boot.js
file. You can use this new file to load or instantiate troublesome packages into your project that really want to be the first thing you load. Packages likenewrelic
ordotenv
are these types of packages. Another use-case would be to configure your environment via an external source.π You can see the contents of
boot.js
to add to an existing project here https://github.com/actionhero/actionhero/blob/master/bin/templates/boot.jsreEnqueuePeriodicTaskIfException
Now, if a periodic task fails, it will still be run again. This behavior is what the majority of Actionhero uses had expected was happening all along, so hopefully this change is less surprising for new Acitonhero users.
0οΈβ£ A new option has been added to tasks,
reEnqueuePeriodicTaskIfException
with the default value oftrue
. If you want your tasks to not be re-enqueued should they throw an exception, you can setreEnqueuePeriodicTaskIfException = false
.Via #1309 and 72fb343 by @dasagan
β‘οΈ Updated logging levels
β‘οΈ This change updates Actionhero's internal logging levels to more closely match The syslog protocol (RFC 5424). The details can be seen in the Pull Request.
Via #1314 by @aurasalexander
api.config.general.developmentModeForceRestart
β‘οΈ This new option updates ActionHero's development mode to "full" restart when an Action or Task changes, rather than a soft restart. This can be handy if you add a new initializer, param, or route.
Via #1313 by @aurasalexander
-
v19.1.4 Changes
May 27, 2019Misc
- β‘οΈ Update Dependancies to latest versions
-
v19.1.3 Changes
April 03, 2019v19.1.3
Async
connection.create
middleware- by @alimvedats via #1286
Extend resque queue connection options from config
Misc
- β Test node v11
- β‘οΈ Update Dependancies
-
v19.1.2 Changes
February 17, 2019β Added strict transport security header as a default in web server config
β‘οΈ Update config merge behavior to not clobber data with empty objects
- by @shookie and @evantahler via #1283 and #1288
π Flatten task logs so they appear when logged to the CLI
- by @evantahler via 1aa8337