The ultimate solution to execute simple tasks in Nest.js environment fully supporting import of Nest.js classes, basic tools and approaches.
Preview
Description
@polar-rules/nest-task
is the ultimate tool for generating and executing tasks within
Nest.js environment using its
classes, services, etc. We are fully following Nest.js
conventions, rules and approaches to make our library as simple and as familiar as Nest.js itself.
Under the hood we are using the same tool set as Nest.js do: Reflect, class-transformer, class-validator, etc.
More documentation can be found on our website.
Features
- Easy Setup: Quickly set up and integrate tasks within your Nest.js environment with a simple setup command.
-
Support ESM & CJS: Fully support latest modules,
CJS
andESM
. - Convention-based: Follows Nest.js conventions and supports different file naming conventions for flexibility.
-
Interactive Assistant: Use the interactive assistant (
bear
) for a more human-friendly and guided experience. - CLI Commands: Execute a variety of commands for task creation, information retrieval, and task execution.
- Documentation: Well-documented with examples and explanations to guide users through the process.
Table of content
Getting started
Nest.js version
At this point we support only 10.x.x version of Nest.js (at least this is the version that is fully tested), however this package should theoretically work with 9.x.x and lower, but it wasn't tested.
Installation
Via NPM
:
npm install @polar-rules/nest-task
Via Yarn
:
yarn add @polar-rules/nest-task
Help
From command line you can call help prompt to receive a list of available commands:
npx nest-task help
Guides
Once you've installed you will have available nest-task
binary available to run. We recommend you to run npx
to run
binary, but you choose whatever suits you the best.
Now you need to run:
npx nest-task setup --convention kebab-case
In case you have project
key inside your nest-cli.json
you need to add --project-name
flag and specify project
name. For example:
npx nest-task setup --project-name <project> --convention kebab-case
Or run interactive assistant and pick Setup
option, and then just follow installation steps:
npx nest-task bear
This action will do the following:
- modify the
nest-cli.json
and create new keytask
there - create the folder
tasks
undersrc
- create
main.ts
andtasks.module.ts
- create a simple
example
task for education purposes
Creating task
To create a task you need to run:
npx nest-task create --name <name> --description <description>
Or if you have project
key inside your nest-cli.json
you need to add --project-name
flag and specify project
name.
npx nest-task create --project-name <project> --name <name> --description <description>
You can run interactive assistant and pick create
option and just follow proposed steps to generate task:
npx nest-task bear
Receiving the list of tasks
IMPORTANT. In purpose for your tasks run correctly you need to build your project firstly.
To receive a list of tasks
npx nest-task info
Or if you have project
key inside your nest-cli.json
you need to add --project-name
flag and specify project
name.
npx nest-task info --project-name <project>
You can run interactive assistant and pick info
option and just follow proposed steps to generate task:
npx nest-task bear
Running task
IMPORTANT. In purpose for your tasks run correctly you need to build your project firstly.
To create a task you need to run:
npx nest-task run --name <name> <other-arguments>
Or if you have project
key inside your nest-cli.json
you need to add --project-name
flag and specify project
name.
npx nest-task run --project-name <project> --name <name> <other-arguments>
You can run interactive assistant and pick run
option and just follow proposed steps to generate task:
npx nest-task bear
Running task without CLI
Yes, starting from 0.2.0
you can run tasks without CLI and directly using node
command totally bypassing the case
when default Nest.js configuration is not available. All you need to do is to call compiled main.js
file with correct
arguments.
Note: In case you don't have package.json
or for some reason you're missing nest-cli.json
on your server
youre force to run this commands directly.
To pass arguments you need literally to do the same thing as you do with default CLI command.
For example:
node ./dist/task/main.js --name <name> <other-arguments>
Since you're calling main.ts
file directly you don't need to handle project name at all, since we assume that you're
that location of main.js
already in default or under correct directory.
If you want to pass additional arguments, it's easy to do with the following syntax:
node ./dist/task/main.js --name <name> --argument1 value
Note:
--argument1
- can have any desired name, except pre-defined fields, like name
, projectName
and other.
Documentation
Nest integration
In purpose to integrate with Nest.js we modify nest-cli.json
file located inside your root directory. We add
key task
in this file on top level. The object should have the following format:
<root>/nest-cli.json
{
"task": {
"path": "src/tasks",
"entryPoint": "main.ts",
"convention": "kebab-case",
"distDirectory": "dist"
}
}
Or if you use projects
feature from Nest.js then your nest-cli.json
should look like this:
<root>/nest-cli.json
{
"projects": {
"example": {
"task": {
"path": "src/tasks",
"entryPoint": "main.ts",
"convention": "kebab-case",
"distDirectory": "dist"
}
}
}
}
distDirectory
Optional.
By default, we assume that your script is compiled to the "dist"
directory.
So for example, in default setup, you use your "dist"
folder as compiled folder. This is basically where we will be
looking for tasks when you're using CLI. (This will be ignored when you're using node
command on entrypoint directly).
But, sometimes your configuration on server may be a bit different, since sometimes you're deploying your project as is, which may
include you dist folder, and in this case you don't need to do anything, but there may the cases when transpiled
code is located in other directory (not the on that is mentioned in tsconfig
). So in this case we will recommend you
to use specific path to this directory.
We're heavy really on package.json
location and build our path to task from package.json
and we assume that this
is the project root. Then we will use distDirectory
as a next folder from there.
For example this is how we build path <package.json root folder>/${distDirectory}/${path.replace("src", "")/${entryPoint}}
path
Required.
Refers to directory where tasks will be held. By default, we set it to src/tasks
but you're free to
change it to another directory as you will.
entryPoint
Required.
The main file name entrypoint should be present here, this file should be present with in
directory specified in path
key.
conventions
Required.
Directive the specifies what kind of file naming convention we should use when using create
command. Available options are: "camel-case"
, "snake-case"
, "kebab-case"
or "polar-rules"
.
Entrypoint
Entrypoint file, main.ts
it's similar to Nest.js main.ts
file. Basically after you run npx nest-task setup
you
don't need to change it, except the cases when you want to use custom paths.
Its implementation is straight forward, and one time. You don't need make changes afterward.
<root>/src/tasks/main.ts
import { Factory } from "@polar-rules/nest-task";
import { TasksModule } from "./tasks.module";
async function main(): Promise<void> {
const app = await Factory.create(TasksModule);
await app.run();
}
main();
The only thing that you can possibly would like to change here is path to TasksModule
in case of custom setup.
TasksModule
The implementation is close to Nest.js @Module
implementation.
<root>/src/tasks/tasks.module.ts
import { Decorators } from "@polar-rules/nest-task";
import { ExampleTask } from "./example/example.task";
@Decorators.Module({
tasks: [
ExampleTask,
],
})
export class _Module {}
tasks
Required.
Array of Task
classes.
Task
Defining Task
class.
<root>/src/tasks/example/example.task.ts
import { Decorators } from "@polar-rules/nest-task";
import { AppModule } from "../../app.module";
import { AppService } from "../../app.service";
import { ExampleRunner } from "./example.runner";
@Decorators.Task({
name: "Example",
description: "Task created for demonstration how to create basic example of task",
runner: ExampleRunner,
module: AppModule,
providers: [AppService],
deprecated: false,
})
export class ExampleTask {}
Overall, you already familiar with the syntax of this approach.
name
Required.
Unique.
Name of the tasks. Should be unique for @Decorators.Module
. Used to located task, provider information about the task.
description
Required.
Short description of the task. Even if we do not have any limitation for length, we still recommend to keep it simple as possible.
runner
Required.
Your @Decorators.Runner
class that will be covered in the next step. This class wil be the only class that will be
executed by the task.
module
Required.
Main Nest.js application module is required to correctly initialise Nest.js environment.
providers
Optional.
Array of Nest.js services, entities and just classes that you want to use withing task in a same way as you do this
within @Controller
, @Injectable
, etc.
deprecated
Optional.
Boolean value. Literally a flag that blocks you from running the task. Useful in cases when your task is meant to be run only one time and you want to avoid issues with running it second time.
Defining Runner
class.
<root>/src/tasks/example/example.runner.ts
import { INestApplication, Logger } from "@nestjs/common";
import { Decorators } from "@polar-rules/nest-task";
import { ExampleDto } from "./example.dto";
@Decorators.Runner()
export class _Runner {
public constructor(private readonly appService: AppService) {}
public async perform(@Decorators.App() app: INestApplication, @Decorators.Logger() logger: Logger, @Decorators.Arguments() args: ExampleDto): Promise<void> {
// Your code goes here
}
}
providers
Are matched from @Decorators.Task
providers
field into constructor
by type. The same way as you do with Nest.js.
app
By using @Decorators.App()
for an argument you can pass the Nest.js application variable.
logger
By using @Decorators.Logger()
for an argument you can pass the Nest.js default logger.
Now you can use as you would use default logger that is coming from Nest.js.
logger.log("Example")
args
If you need to pass additional arguments from command line to the task you can use @Decorators.Arguments()
with DTO
in a same way as you do for Nest.js @Controller
.
Defining DTO
class.
<root>/src/tasks/example/example.dto.ts
import { Type } from "class-transformer";
import { IsNumber, IsString } from "class-validator";
import { Decorators } from "@polar-rules/nest-task";
export class ExampleDto {
@Decorators.Property()
@Type(() => String)
@IsString()
data: string;
@Decorators.Property()
@Type(() => IsNumber)
@IsNumber()
userId: number;
}
The same way that you do with Nest.js DTO.
However
Even due class-transformer
library do support complex types, as array, object, etc. And theoretically we can do this
too, but we still recommend to use simple primitive types like:
- string
- number
- boolean
- null
- undefined
If you want to use more complex type we recommend to use string and JSON combination.
class and variable naming.
CLI
More details CLI documentation you can read CLI Documentation section.
Issues
Please make sure to read the Issue Reporting Checklist before opening an issue. Issues not conforming to the guidelines may be closed immediately.
- We're heavy really on
package.json
location and build our path to task frompackage.json
and we assume that this is the project root, when you're using our CLI, hence do development be sure that you have package.json inside your project. Same rules applied when you're running our CLI on server that's why you need to be sure that you havepackage.json
on your server, if you want to use CLI. In case, for some reason you don't havepackage.json
on server - then you can run your tasks withnode entrypoint.js
command.
Contributing
We welcome contributions! Please read our Contribution Guidelines before submitting a pull request.
Stay in touch
- Author - Andrii Drozdov
Acknowledgments
- The
@nestjs/cli
for providing a solid foundation for Nest.js projects. - The
class-validator
andclass-transformer
for easy class validation
License
Released under MIT by @polar-rules.