Skip to content

Commit c65d31d

Browse files
authored
Merge pull request #10 from JooLuiz/feat/enhancing-browse-automation-action
Feat/enhancing browse automation action
2 parents cab43ea + fe29653 commit c65d31d

75 files changed

Lines changed: 3409 additions & 2026 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,4 +130,8 @@ dist
130130
.pnp.*
131131

132132
# ignoring configs
133-
config/config.json
133+
config/config.json
134+
135+
# Scheduled tasks - ignore everything except the example file
136+
scheduled-tasks/*
137+
!scheduled-tasks/setup-scheduled-task.example.ps1

README.md

Lines changed: 189 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -76,78 +76,201 @@ npm install
7676

7777
## 3. Available Commands
7878

79-
### 3.1 login
79+
### 3.1 action-runner
8080

8181
#### 3.1.1 Specifications
8282

83-
The `login` command opens a browser and logs in according to the settings. It accepts the following parameters:
83+
The `action-runner` command executes one action flow from `actionRunner`, which can include browser automation, API requests, and shell commands. It accepts the following parameters:
8484

85-
| Long Parameter | Short Parameter | Required | Description |
86-
| -------------- | --------------- | -------- | -------------------------------------------------- |
87-
| --action | -a | YES | Indicates the action the login will perform |
88-
| --verbose | -v | NO | Indicates whether to display logs during execution |
85+
| Long Parameter | Short Parameter | Required | Description |
86+
| -------------------- | --------------- | -------- | --------------------------------------------------- |
87+
| --action | -a | YES | Indicates the action the action-runner will perform |
88+
| --verbose | -v | NO | Indicates whether to display logs during execution |
89+
| --arg.\<name\>=value || NO | Passes a custom argument into the action's context |
90+
91+
**Custom arguments** let you pass values from the CLI into any action. For example:
92+
93+
```powershell
94+
action-runner --action=perform-api-request "--arg.message=Hello from CLI"
95+
```
96+
97+
Inside the action, `{{context.message}}` resolves to `"Hello from CLI"` (after a `getArguments` step maps it).
8998

9099
#### 3.1.2 Configuration
91100

92-
Before using the `login` command, you need to configure the desired actions. To do this, you need to create the `config.json` file in the `./config/` directory. There is an example of how this config should look in the same folder, and it is structured like this:
101+
Before using the `action-runner` command, you need to configure the desired actions. To do this, you need to create the `config.json` file in the `./config/` directory. There is an example of how this config should look in the same folder (`config-example.json`).
102+
103+
Each action under `actionRunner` supports one of two formats:
104+
105+
**Simple login (legacy flat fields)** — username, password, then submit:
93106

94107
```json
95108
{
96-
"browseAndLogin": {
97-
"[actions]": {
98-
"url": "",
99-
"usernameInput": "",
100-
"usernameValue": "",
101-
"passwordInput": "",
102-
"passwordValue": "",
103-
"loginButton": ""
109+
"actionRunner": {
110+
"simple-login": {
111+
"url": "https://example.com/login",
112+
"usernameInput": "#email",
113+
"usernameValue": "user@example.com",
114+
"passwordInput": "#password",
115+
"passwordValue": "your-password",
116+
"loginButton": "#submit"
104117
}
105118
}
106119
}
107120
```
108121

109-
Let's say you want to create a command that logs into your email. To do this, just replace "[action]" with "log-email" and fill in the other fields according to the access form IDs and your data.
122+
**Multi-step login (`steps` array)** — use when you need extra clicks, waits, or a custom order (e.g. click "Next" after username):
110123

111-
> **_TIP:_** as browseAndLogin is an object of objects, you can have `n` login actions for different sites, as long as you add them to the config file properly.
124+
```json
125+
{
126+
"actionRunner": {
127+
"multi-step-login": {
128+
"steps": [
129+
{ "action": "navigate", "url": "https://example.com/login" },
130+
{ "action": "type", "selector": "#username", "value": "your-username" },
131+
{
132+
"action": "click",
133+
"selector": "#nextBtn",
134+
"waitForSelector": "#password"
135+
},
136+
{ "action": "type", "selector": "#password", "value": "your-password" },
137+
{ "action": "click", "selector": "#loginbtn" }
138+
]
139+
}
140+
}
141+
}
142+
```
112143

113-
Now you need to configure the command in your `$PROFILE`, as mentioned in step 1.2 of this README.
144+
Supported step `action` values:
114145

115-
So, just add the following code to `$PROFILE`:
146+
| action | required fields | optional fields |
147+
| ----------------- | -------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
148+
| `navigate` | `url` ||
149+
| `type` | `selector`, `value` | `delay`, `waitForLoading`, `timeout` |
150+
| `click` | `selector` | `waitForNavigation`, `waitForUrl`, `waitForSelector`, `waitForLoading`, `timeout` (ms, default 30000), `jsClick`, `iframe` |
151+
| `wait` | `ms`, `selector`, `urlContains`, or `waitForLoading` | `timeout` (when using `selector`, `urlContains`, or `waitForLoading`) |
152+
| `setWebStorage` | at least one of `localStorage`, `sessionStorage`, or `cookies` ||
153+
| `closeBrowser` |||
154+
| `forEachElement` | `selector`, `steps` | `textContentSelector`, `excludeTextPatterns`, `clickSelector`, `skipIfPositionMatch` |
155+
| `apiRequest` | `url` | `method`, `params`, `headers`, `auth`, `body`, `timeout`, `ignoreHttpErrors`, `storeAs` |
156+
| `extractVariable` | `source`, `storeAs` ||
157+
| `shell` | `command` or `commands` | `cwd`, `shell`, `timeout`, `ignoreExitCode`, `maxBuffer`, `storeAs` |
158+
| `getArguments` || `required`, `optional`, `defaults` |
159+
| `invokeAction` | `name` | `args`, `continueOnError`, `storeAs` |
160+
| `tryCatch` | `try` | `catch`, `finally` |
116161

117-
```powershell
118-
New-Alias -Name login -Value Path\To\Your\Cloned\Repo\browse-and-login\browse-and-login.bat
162+
**`setWebStorage`** injects data into the browser's web storage or cookies. This is useful for pre-authenticating sessions that require complex login flows (e.g. OTP codes). Values that are objects or arrays are automatically `JSON.stringify`-ed before being stored. Cookies use Puppeteer's native `page.setCookie()` format.
119163

120-
Function log-email {
121-
param (
122-
[string[]]$ExtraArgs
123-
)
124-
$loginCommand = "login"
125-
$loginCommand += " --action=log-email"
126-
echo $ExtraArgs
127-
foreach ($arg in $ExtraArgs) {
128-
echo $arg
129-
if ($arg.StartsWith("--")) {
130-
$loginCommand += " $arg"
131-
} elseif ($arg.StartsWith("-")) {
132-
$loginCommand += " $arg"
133-
} else {
134-
$loginCommand += " '$arg'"
164+
Example:
165+
166+
```json
167+
{
168+
"action": "setWebStorage",
169+
"localStorage": {
170+
"token": "your-jwt-token",
171+
"user": { "id": "123", "name": "john" }
172+
}
173+
}
174+
```
175+
176+
> **_NOTE:_** `setWebStorage` must be used **after** a `navigate` step to the target domain, since localStorage/sessionStorage is bound to the page origin. To apply the injected session, add another `navigate` step after `setWebStorage` to reload the page.
177+
178+
**`closeBrowser`** gracefully closes the browser instance. Typically used as the last step in an action.
179+
180+
**`apiRequest`** calls HTTP endpoints directly. You can persist response data into runtime context with `storeAs`, then reuse it in later steps.
181+
182+
**`extractVariable`** stores a resolved value into context. Useful to assign short names such as the first task id.
183+
184+
**`shell`** executes shell commands (PowerShell by default) and can store command output in context.
185+
186+
**`getArguments`** validates and maps CLI arguments (passed via `--arg.<name>=<value>`) or parent-action arguments (via `invokeAction`) into the runtime context. Use `required` to list mandatory arguments (throws if missing), `optional` to list arguments that are mapped only when present, and `defaults` to provide fallback values for missing ones.
187+
188+
**`invokeAction`** calls another action defined in `actionRunner` config by name. The child action runs with an isolated context seeded from `args`. Use `storeAs` to copy the child's final context back into the parent. `continueOnError: true` prevents child failures from aborting the parent action. Recursion is capped at 5 levels.
189+
190+
Example of a composable action:
191+
192+
```json
193+
{
194+
"actionRunner": {
195+
"perform-api-request": {
196+
"steps": [
197+
{ "action": "getArguments", "required": ["message"] },
198+
{
199+
"action": "apiRequest",
200+
"method": "POST",
201+
"url": "https://api.example.com/v1/notify",
202+
"params": {
203+
"userId": "{{env.GENERIC_USER_ID}}",
204+
"message": "{{context.message}}",
205+
"apiKey": "{{env.GENERIC_API_KEY}}"
206+
},
207+
"ignoreHttpErrors": true
208+
}
209+
]
210+
},
211+
"my-workflow": {
212+
"steps": [
213+
{ "action": "shell", "command": "echo 'doing work'" },
214+
{
215+
"action": "invokeAction",
216+
"name": "perform-api-request",
217+
"args": { "message": "workflow completed" },
218+
"continueOnError": true
135219
}
220+
]
136221
}
137-
Invoke-Expression $loginCommand
222+
}
138223
}
139224
```
140225

141-
What this configuration does is define an alias called login that runs the browse-and-login.bat file in this repository, then creates a function that executes the newly created "login" command, passing by default the argument `--action=log-email`. So, the following commands are equivalent:
226+
**`tryCatch`** wraps steps in try/catch/finally semantics. If any step in `try` throws, the error message is stored in `context.errorMessage` and the `catch` steps run. `finally` steps always run regardless of success or failure. If no `catch` is defined, the error re-throws to the parent flow.
142227

143-
```shell
144-
login --action=log-email
228+
Example:
229+
230+
```json
231+
{
232+
"action": "tryCatch",
233+
"try": [
234+
{ "action": "shell", "command": "some-risky-command" },
235+
{
236+
"action": "invokeAction",
237+
"name": "perform-api-request",
238+
"args": { "message": "task completed successfully" }
239+
}
240+
],
241+
"catch": [
242+
{
243+
"action": "invokeAction",
244+
"name": "perform-api-request",
245+
"args": { "message": "task failed, error: {{context.errorMessage}}" }
246+
}
247+
]
248+
}
145249
```
146250

147-
&
251+
### Dynamic placeholders
148252

149-
```shell
150-
log-email
253+
All string fields in steps support interpolation:
254+
255+
- `{{context.some.path}}` reads values produced by earlier steps.
256+
- `{{env.VARIABLE_NAME}}` reads environment variables from your machine.
257+
258+
Example:
259+
260+
```json
261+
{
262+
"action": "apiRequest",
263+
"url": "{{API_URL}}",
264+
"params": {
265+
"firstParam": "paramFirst"
266+
},
267+
"auth": {
268+
"type": "basic",
269+
"username": "email@example.com",
270+
"password": "{{env.PASSKEY}}"
271+
},
272+
"storeAs": "apiResponse"
273+
}
151274
```
152275

153276
### 3.2 touch
@@ -180,38 +303,43 @@ Similarly to the previous command and as mentioned in section 1.2 of this README
180303
New-Alias -Name reinitialize -Value Path\To\Your\Cloned\Repo\reinitialize\reinitialize.bat
181304
```
182305

183-
### 3.4 scheduler
306+
### 3.4 Scheduled Tasks
184307

185308
#### 3.4.1 Specifications
186309

187-
The `scheduler` command opens a browser and shows the list of scheduled jobs of the computer, it allows the CRUD actions for scheduled jobs. The command saves the scheduled jobs in a temporary file and starts a node server to serve the html files and routes, by default the command starts in a separated
310+
The `scheduled-tasks/` folder contains an example PowerShell script that creates a Windows Scheduled Task to run any custom command on a recurring schedule. It uses `Register-ScheduledTask` to create a task with configurable weekly triggers. The task loads your `$PROFILE` before executing so that custom functions and aliases are available.
188311

189-
It accepts the following parameters:
190-
191-
| Long Parameter | Short Parameter | Required | Description |
192-
| -------------- | --------------- | -------- | ----------------------------------------------------------- |
193-
| \_start\_ | | NO | Starts the server in the same terminal that ran the command |
194-
| --verbose | -v | NO | Indicates whether to display logs during execution |
312+
You can find the example at `scheduled-tasks/setup-scheduled-task.example.ps1`.
195313

196314
#### 3.4.2 Configuration
197315

198-
Before using the `scheduler` command, you need to configure the server port that should be used (the default is 3002) and to insert the computer user password because this is needed to update scheduled tasks. To do this, you need to create/update the `config.json` file in the `./config/` directory. There is an example of how this config should look in the same folder, and it is structured like this:
316+
1. Copy the example file and rename it (e.g. `setup-my-task.ps1`).
317+
2. Open the copy and replace the placeholders:
318+
- `$TaskName` — set a unique name for your scheduled task.
319+
- `$triggerTimes` — set the times you want it to trigger (24h format).
320+
- `$weekdays` — set the days of the week.
321+
- `{{YOUR_COMMAND_HERE}}` — replace with the command or function you want to run (e.g. a function defined in your `$PROFILE`).
199322

200-
```json
201-
{
202-
"scheduler": {
203-
"serverPort": 3002,
204-
"userPassword": ""
205-
}
206-
}
323+
3. Run the script once from an **elevated** (Administrator) PowerShell terminal:
324+
325+
```powershell
326+
.\scheduled-tasks\setup-my-task.ps1
207327
```
208328

209-
Similarly to the previous command and as mentioned in section 1.2 of this README, you need to configure the command in `$PROFILE`. Once the profile is open, the command looks like this:
329+
To remove a scheduled task:
210330

211331
```powershell
212-
New-Alias -Name scheduler -Value Path\To\Your\Cloned\Repo\scheduler\scheduler.bat
332+
.\scheduled-tasks\setup-my-task.ps1 -Remove
213333
```
214334

335+
You can verify the task was created with:
336+
337+
```powershell
338+
Get-ScheduledTask -TaskName "YourTaskName" | Get-ScheduledTaskInfo
339+
```
340+
341+
> **_NOTE:_** make sure the command you reference is already defined in your `$PROFILE` before running the setup script, since the scheduled task depends on it.
342+
215343
# Other versions
216344

217345
[Readme in Portuguese (PT-BR)](README.pt-br.md)

0 commit comments

Comments
 (0)