From 4aca28d64fcaf9b5d329b500d7c88097f32b681f Mon Sep 17 00:00:00 2001 From: Evan Tahler Date: Sun, 11 Oct 2020 15:06:14 -0700 Subject: [PATCH] Replace `require` with `await import` where possible (#1614) * Replace require with await import * change to for-loop for clarity --- __tests__/core/cli.ts | 4 +++- __tests__/core/staticFile/staticFile.ts | 3 ++- __tests__/integration/browser.ts | 5 ++++- src/actions/status.ts | 12 ++++++++--- src/bin/actionhero.ts | 27 ++++++++++++------------ src/bin/methods/generate/plugin.ts | 12 +++++------ src/bin/methods/help.ts | 7 +++--- src/bin/methods/version.ts | 6 +++++- src/classes/action.ts | 3 ++- src/classes/process.ts | 7 +++--- src/classes/process/actionheroVersion.ts | 13 ++++++------ src/classes/task.ts | 3 ++- src/config/api.ts | 9 ++++++-- src/config/redis.ts | 9 +++++--- src/config/servers/web.ts | 2 +- src/initializers/actions.ts | 2 +- src/initializers/servers.ts | 2 +- src/initializers/tasks.ts | 27 ++++++++++++------------ src/modules/specHelper.ts | 4 ++++ src/modules/task.ts | 2 +- templates/boot.js.template | 2 +- 21 files changed, 95 insertions(+), 66 deletions(-) diff --git a/__tests__/core/cli.ts b/__tests__/core/cli.ts index ea525ed3a..f1bc809f0 100644 --- a/__tests__/core/cli.ts +++ b/__tests__/core/cli.ts @@ -9,7 +9,9 @@ import * as isrunning from "is-running"; const testDir = path.join(process.cwd(), "tmp", "actionheroTestProject"); const binary = "./node_modules/.bin/actionhero"; -const pacakgeJSON = require(path.join(__dirname, "/../../package.json")); +const pacakgeJSON = JSON.parse( + fs.readFileSync(path.join(__dirname, "/../../package.json")).toString() +); console.log(`testDir: ${testDir}`); diff --git a/__tests__/core/staticFile/staticFile.ts b/__tests__/core/staticFile/staticFile.ts index 3bdea987b..88f25e838 100644 --- a/__tests__/core/staticFile/staticFile.ts +++ b/__tests__/core/staticFile/staticFile.ts @@ -1,4 +1,5 @@ import * as request from "request-promise-native"; +import * as child_process from "child_process"; import { Process, config, utils, specHelper } from "../../../src/index"; const actionhero = new Process(); @@ -6,7 +7,7 @@ let url; async function exec(command) { return new Promise((resolve, reject) => { - require("child_process").exec(command, (error, stdout, stderr) => { + child_process.exec(command, (error, stdout, stderr) => { if (error) { return reject(error); } diff --git a/__tests__/integration/browser.ts b/__tests__/integration/browser.ts index b2ed36d3a..e971c4f5f 100644 --- a/__tests__/integration/browser.ts +++ b/__tests__/integration/browser.ts @@ -3,8 +3,11 @@ */ import * as path from "path"; +import * as fs from "fs"; import { api, Process, config } from "./../../src/index"; -const packageJSON = require(path.join(__dirname, "..", "..", "package.json")); +const packageJSON = JSON.parse( + fs.readFileSync(path.join(__dirname, "..", "..", "package.json")).toString() +); const host = process.env.SELENIUM_TEST_HOST || "localhost"; const actionhero = new Process(); diff --git a/src/actions/status.ts b/src/actions/status.ts index adc333953..6b12e0004 100644 --- a/src/actions/status.ts +++ b/src/actions/status.ts @@ -1,8 +1,14 @@ import { api, id, task, Action, actionheroVersion } from "./../index"; import * as path from "path"; -const packageJSON = require(path.normalize( - path.join(__dirname, "..", "..", "package.json") -)); +import * as fs from "fs"; + +const packageJSON = JSON.parse( + fs + .readFileSync( + path.normalize(path.join(__dirname, "..", "..", "package.json")) + ) + .toString() +); // These values are probably good starting points, but you should expect to tweak them for your application const maxEventLoopDelay = process.env.eventLoopDelay || 10; diff --git a/src/bin/actionhero.ts b/src/bin/actionhero.ts index bbe5ea567..c529562b9 100755 --- a/src/bin/actionhero.ts +++ b/src/bin/actionhero.ts @@ -74,11 +74,9 @@ const projectRoot = determineProjectRoot(); const handleUnbuiltProject = async (commands: Array) => { try { // when generating the project from scratch, we cannot rely on the normal initializers - const ExportedRunnerClasses = require(path.join( - __dirname, - "methods", - commands.join(path.sep) - )); + const ExportedRunnerClasses = await import( + path.join(__dirname, "methods", commands.join(path.sep)) + ); if (Object.keys(ExportedRunnerClasses).length > 1) { throw new Error("actionhero CLI files should only export one method"); @@ -101,7 +99,7 @@ const projectRoot = determineProjectRoot(); console.log(`ACTIONHERO COMMAND >> ${commands.join(" ")}`); console.log("⁻⁻⁻⁻⁻⁻⁻⁻⁻⁻⁻⁻⁻⁻⁻⁻⁻⁻⁻⁻⁻⁻⁻⁻⁻⁻⁻⁻⁻⁻⁻⁻⁻⁻⁻⁻⁻⁻"); - const { config, Process } = require(path.join(__dirname, "..", "index")); + const { config, Process } = await import("../index"); const actionHeroProcess = new Process(); await actionHeroProcess.initialize(); @@ -111,26 +109,27 @@ const projectRoot = determineProjectRoot(); let p: string; p = path.join(__dirname, "methods", commands.join(path.sep) + ".js"); if (fs.existsSync(p) && config.general.cliIncludeInternal !== false) { - ExportedClasses = require(p); + ExportedClasses = await import(p); } p = path.join(__dirname, "methods", commands.join(path.sep) + ".ts"); if (fs.existsSync(p) && config.general.cliIncludeInternal !== false) { - ExportedClasses = require(p); + ExportedClasses = await import(p); } if (!ExportedClasses) { - config.general.paths.cli.forEach((cliPath: string) => { + for (const i in config.general.paths.cli) { + const cliPath = config.general.paths.cli[i]; p = path.join(cliPath, commands.join(path.sep) + ".js"); if (fs.existsSync(p)) { - ExportedClasses = require(p); + ExportedClasses = await import(p); } p = path.join(cliPath, commands.join(path.sep) + ".ts"); if (fs.existsSync(p)) { - ExportedClasses = require(p); + ExportedClasses = await import(p); } - }); + } } if (!ExportedClasses) { @@ -139,7 +138,7 @@ const projectRoot = determineProjectRoot(); const pluginPath = config.plugins[pluginName].path; p = path.join(pluginPath, "bin", commands.join(path.sep) + ".js"); if (fs.existsSync(p)) { - ExportedClasses = require(p); + ExportedClasses = await import(p); } p = path.join( @@ -149,7 +148,7 @@ const projectRoot = determineProjectRoot(); commands.join(path.sep) + ".js" ); if (fs.existsSync(p)) { - ExportedClasses = require(p); + ExportedClasses = await import(p); } } } diff --git a/src/bin/methods/generate/plugin.ts b/src/bin/methods/generate/plugin.ts index dd14046fa..4fa1f19f6 100644 --- a/src/bin/methods/generate/plugin.ts +++ b/src/bin/methods/generate/plugin.ts @@ -2,13 +2,11 @@ import * as fs from "fs"; import * as path from "path"; import { CLI, utils } from "./../../../index"; -const PackageJSON = require(path.join( - __dirname, - "..", - "..", - "..", - "package.json" -)); +const PackageJSON = JSON.parse( + fs + .readFileSync(path.join(__dirname, "..", "..", "..", "package.json")) + .toString() +); export class GeneratePlugin extends CLI { constructor() { diff --git a/src/bin/methods/help.ts b/src/bin/methods/help.ts index ff6d62bf4..d7c859935 100644 --- a/src/bin/methods/help.ts +++ b/src/bin/methods/help.ts @@ -47,9 +47,10 @@ export class Help extends CLI { files = utils.arrayUnique(files); - files.forEach((f) => { + for (const i in files) { + const f = files[i]; try { - const ExportedClasses = require(f); + const ExportedClasses = await import(f); const req = new ExportedClasses[Object.keys(ExportedClasses)[0]](); if ( req.name && @@ -63,7 +64,7 @@ export class Help extends CLI { methods[req.name] = req; } } catch (e) {} - }); + } const methodNames = Object.keys(methods).sort(); diff --git a/src/bin/methods/version.ts b/src/bin/methods/version.ts index 47ba7b732..6d79e99cd 100644 --- a/src/bin/methods/version.ts +++ b/src/bin/methods/version.ts @@ -1,9 +1,13 @@ import * as path from "path"; +import * as fs from "fs"; + // import { CLI } from "./../../index"; // we need to load each component directly so we don't accidentally source `config... which doesn't exist` import { CLI } from "./../../classes/cli"; -const packageJSON = require(path.join(__dirname, "/../../../package.json")); +const packageJSON = JSON.parse( + fs.readFileSync(path.join(__dirname, "/../../../package.json")).toString() +); export class Version extends CLI { constructor() { diff --git a/src/classes/action.ts b/src/classes/action.ts index efb9aecda..f2ee0774a 100644 --- a/src/classes/action.ts +++ b/src/classes/action.ts @@ -4,7 +4,8 @@ import { api } from "../index"; /** * Create a new Actionhero Action. The required properties of an action. These can be defined statically (this.name) or as methods which return a value. *```js - * const { Action } = require('actionhero') + * import { Action } from "actionhero"; + * * module.exports = class RandomNumber extends Action { * constructor () { * super() diff --git a/src/classes/process.ts b/src/classes/process.ts index 227c5452c..9f7c83f10 100644 --- a/src/classes/process.ts +++ b/src/classes/process.ts @@ -107,13 +107,14 @@ export class Process { initializerFiles = utils.arrayUnique(initializerFiles); initializerFiles = utils.ensureNoTsHeaderFiles(initializerFiles); - initializerFiles.forEach((f) => { + for (const i in initializerFiles) { + const f = initializerFiles[i]; const file = path.normalize(f); if (require.cache[require.resolve(file)]) { delete require.cache[require.resolve(file)]; } - let exportedClasses = require(file); + let exportedClasses = await import(file); // allow for old-js style single default exports if (typeof exportedClasses === "function") { @@ -226,7 +227,7 @@ export class Process { stopInitializerRankings[initializer.stopPriority].push(stopFunction); } } - }); + } // flatten all the ordered initializer methods this.loadInitializers = this.flattenOrderedInitializer( diff --git a/src/classes/process/actionheroVersion.ts b/src/classes/process/actionheroVersion.ts index e20b329c1..e516399e8 100644 --- a/src/classes/process/actionheroVersion.ts +++ b/src/classes/process/actionheroVersion.ts @@ -1,11 +1,10 @@ import * as path from "path"; +import * as fs from "fs"; -const packageJson = require(path.join( - __dirname, - "..", - "..", - "..", - "package.json" -)); +const packageJson = JSON.parse( + fs + .readFileSync(path.join(__dirname, "..", "..", "..", "package.json")) + .toString() +); export const actionheroVersion = packageJson.version; diff --git a/src/classes/task.ts b/src/classes/task.ts index 75318f75f..c058ef39c 100644 --- a/src/classes/task.ts +++ b/src/classes/task.ts @@ -3,7 +3,8 @@ import { Inputs } from "./inputs"; /** * Create a new Actionhero Task. The required properties of an task. These can be defined statically (this.name) or as methods which return a value. * ```js - * const { Task, api, log } = require('actionhero') + * import { Task, api, log } from "actionhero" + * * module.exports = class SayHello extends Task { * constructor () { * super() diff --git a/src/config/api.ts b/src/config/api.ts index b079b21b3..b21908230 100644 --- a/src/config/api.ts +++ b/src/config/api.ts @@ -1,8 +1,13 @@ -const path = require("path"); +import * as path from "path"; +import * as fs from "fs"; export const DEFAULT = { general: (config) => { - const packageJSON = require("./../../package.json"); + const packageJSON = JSON.parse( + fs + .readFileSync(path.join(__dirname, "..", "..", "package.json")) + .toString() + ); return { apiVersion: packageJSON.version, diff --git a/src/config/redis.ts b/src/config/redis.ts index 714c2c634..fb38dec4e 100644 --- a/src/config/redis.ts +++ b/src/config/redis.ts @@ -6,6 +6,9 @@ let db = process.env.REDIS_DB || process.env.JEST_WORKER_ID || "0"; let password = process.env.REDIS_PASSWORD || null; const maxBackoff = 1000; +// this cannot be imported as the ioredis types are not exported for --declaration +const Redis = require("ioredis"); + if (process.env.REDIS_URL) { const parsed = new URL(process.env.REDIS_URL); if (parsed.password) { @@ -51,17 +54,17 @@ export const DEFAULT = { _toExpand: false, client: { - konstructor: require("ioredis"), + konstructor: Redis, args: [commonArgs], buildNew: true, }, subscriber: { - konstructor: require("ioredis"), + konstructor: Redis, args: [commonArgs], buildNew: true, }, tasks: { - konstructor: require("ioredis"), + konstructor: Redis, args: [commonArgs], buildNew: true, }, diff --git a/src/config/servers/web.ts b/src/config/servers/web.ts index 4a42abb2d..63906371e 100644 --- a/src/config/servers/web.ts +++ b/src/config/servers/web.ts @@ -1,4 +1,4 @@ -const os = require("os"); +import * as os from "os"; export const DEFAULT = { servers: { diff --git a/src/initializers/actions.ts b/src/initializers/actions.ts index 12671a8a3..66f34d0cf 100644 --- a/src/initializers/actions.ts +++ b/src/initializers/actions.ts @@ -55,7 +55,7 @@ export class Actions extends Initializer { let action; try { - let collection = require(fullFilePath); + let collection = await import(fullFilePath); if (typeof collection === "function") { collection = [collection]; } diff --git a/src/initializers/servers.ts b/src/initializers/servers.ts index 720f20623..a30d79543 100644 --- a/src/initializers/servers.ts +++ b/src/initializers/servers.ts @@ -61,7 +61,7 @@ export class Servers extends Initializer { for (const j in files) { const filename = files[j]; - const ExportedClasses = require(filename); + const ExportedClasses = await import(filename); const exportLen = Object.keys(ExportedClasses).length; // we have named exports diff --git a/src/initializers/tasks.ts b/src/initializers/tasks.ts index 84f8feb2b..cd3ab9295 100644 --- a/src/initializers/tasks.ts +++ b/src/initializers/tasks.ts @@ -35,9 +35,9 @@ export class Tasks extends Initializer { globalMiddleware: [], }; - api.tasks.loadFile = (fullFilePath: string, reload = false) => { + api.tasks.loadFile = async (fullFilePath: string, reload = false) => { let task; - let collection = require(fullFilePath); + let collection = await import(fullFilePath); for (const i in collection) { const TaskClass = collection[i]; task = new TaskClass(); @@ -134,16 +134,17 @@ export class Tasks extends Initializer { }; }; - api.tasks.loadTasks = (reload) => { - config.general.paths.task.forEach((p) => { - utils - .ensureNoTsHeaderFiles( - glob.sync(path.join(p, "**", "**/*(*.js|*.ts)")) - ) - .forEach((f) => { - api.tasks.loadFile(f, reload); - }); - }); + api.tasks.loadTasks = async (reload) => { + for (const i in config.general.paths.task) { + const p = config.general.paths.task[i]; + await Promise.all( + utils + .ensureNoTsHeaderFiles( + glob.sync(path.join(p, "**", "**/*(*.js|*.ts)")) + ) + .map((f) => api.tasks.loadFile(f, reload)) + ); + } for (const pluginName in config.plugins) { if (config.plugins[pluginName].tasks !== false) { @@ -163,7 +164,7 @@ export class Tasks extends Initializer { } }; - api.tasks.loadTasks(false); + await api.tasks.loadTasks(false); // we want to start the queue now, so that it's available for other initializers and CLI commands await api.resque.startQueue(); diff --git a/src/modules/specHelper.ts b/src/modules/specHelper.ts index 0a6d4c1a6..cdac0ef51 100644 --- a/src/modules/specHelper.ts +++ b/src/modules/specHelper.ts @@ -61,6 +61,10 @@ export namespace specHelper { taskName: string, params: object | Array ): Promise<{ [key: string]: any }> { + if (!api.tasks.tasks[taskName]) { + throw new Error(`task ${taskName} not found`); + } + return api.tasks.tasks[taskName].run(params); } diff --git a/src/modules/task.ts b/src/modules/task.ts index 5bc9d7006..0b92ebef9 100644 --- a/src/modules/task.ts +++ b/src/modules/task.ts @@ -410,7 +410,7 @@ export namespace task { api.tasks.middleware ); } - api.tasks.loadTasks(true); + await api.tasks.loadTasks(true); } async function validateInput(taskName: string, inputs: TaskInputs) { diff --git a/templates/boot.js.template b/templates/boot.js.template index 7e056b625..8e66704a9 100644 --- a/templates/boot.js.template +++ b/templates/boot.js.template @@ -1,4 +1,4 @@ -/* This file will load, be `require()`d, first in the actionhero binary. +/* This file will load, be required, first in the actionhero binary. Anything that needed loaded or run BEFORE actionhero starts can be done here. This file returns a single method that is run immediately after loading.