@polar-rules/nest-task v0.2.0
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,
CJSandESM. - 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-taskVia Yarn:
yarn add @polar-rules/nest-taskHelp
From command line you can call help prompt to receive a list of available commands:
npx nest-task helpGuides
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-caseIn 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-caseOr run interactive assistant and pick Setup option, and then just follow installation steps:
npx nest-task bearThis action will do the following:
- modify the
nest-cli.jsonand create new keytaskthere - create the folder
tasksundersrc - create
main.tsandtasks.module.ts - create a simple
exampletask 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 bearReceiving 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 infoOr 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 bearRunning 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 bearRunning 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 valueNote:
--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.jsonlocation and build our path to task frompackage.jsonand 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.jsonon your server, if you want to use CLI. In case, for some reason you don't havepackage.jsonon server - then you can run your tasks withnode entrypoint.jscommand.
Contributing
We welcome contributions! Please read our Contribution Guidelines before submitting a pull request.
Stay in touch
- Author - Andrii Drozdov
Acknowledgments
- The
@nestjs/clifor providing a solid foundation for Nest.js projects. - The
class-validatorandclass-transformerfor easy class validation
License
Released under MIT by @polar-rules.