Skip to content

Commit c57a15a

Browse files
Merge pull request #235 from beakerandjake/feature/232-deprecate-action-chains
Feature/232 deprecate action chains
2 parents 5edb330 + 074d042 commit c57a15a

File tree

161 files changed

+3966
-5000
lines changed

Some content is hidden

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

161 files changed

+3966
-5000
lines changed

.eslintrc.cjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ module.exports = {
1919
},
2020
rules: {
2121
'import/prefer-default-export': 'off',
22-
'import/extensions': 'off',
22+
'import/extensions': ['error','ignorePackages'],
2323
'no-console': 'off',
2424
'no-restricted-syntax': 'off',
2525
'max-classes-per-file': 'off',

.prettierrc.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11
{
2-
"printWidth": 90,
32
"singleQuote": true
43
}

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

88
## [Unreleased]
9+
### Added
10+
- Add devDependencies: jest-extended
11+
912
### Changed
1013
- Input files are ignored in source control by default ([#231](https://github.com/beakerandjake/advent-of-code-runner/issues/231))
14+
- Deprecate action chains and major rewrite of commands ([#232](https://github.com/beakerandjake/advent-of-code-runner/issues/232))
15+
- All commands have much better unit testing.
16+
- Logging output less verbose when running commands.
17+
- Upgrade dependencies: commander 11.1.0
18+
- Upgrade devDependencies: jest 29.7.0
1119

1220
## [1.4.0] - 2023-11-13
1321
### Added

CONTRIBUTING.md

Lines changed: 6 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ Pull requests run a CI workflow, which must pass for the PR to be merged.
3838
#### Additional Pull Request Tips
3939
- Try to focus on accomplishing one thing, be it a feature or a bug fix.
4040
- Try to do the least amount of change possible to accomplish the goal.
41-
- Skip the temptation to make unnecessary changes or refactors (this makes tracing changes easier in the future).
41+
- Skip the temptation to make unnecessary changes or refactors (this makes tracking changes easier in the future).
4242
- If possible try not to introduce new dependencies.
4343

4444
## Development Setup
@@ -61,7 +61,7 @@ npm install
6161
```
6262

6363
#### `npm start`
64-
This is the command to run the program for development. It runs the `scripts/start.js` file.
64+
This is the command to run the program for development. It runs the `bin/start.js` file.
6565

6666
This file contains some logic to ensure local development is easy:
6767
- A working directory is created (if it does not exist) at the root of the repository called `development`. This folder acts as the cwd when running commands, it is ignored by git.
@@ -94,44 +94,16 @@ The project folder structure attempts to be as flat as possible to avoid deep ne
9494
Each js file strives to have a single purpose, and if it starts to do too much it should be split into different files. This makes finding the implementation of a feature easy and makes the code more testable. Big multipurpose files are generally avoided save for some exceptions such as `util.js` or `formatting.js`.
9595

9696
#### Folders
97-
- `scripts/` contains development scripts launched by the `package.json`
97+
- `bin/` contains development scripts launched by the `package.json`
9898
- `src/` contains all source code necessary to run the CLI.
9999
- `templates/` template files used by the `init` command.
100100
- `tests/` the unit tests, matches the structure of `src/`
101101

102102
## Code overview
103-
This project uses [commander](https://github.com/tj/commander.js/) for the CLI logic. In `main.js` you can see all of the commands that are added. Each command corresponds to a file in the `src/cli` folder.
103+
This project uses [commander](https://github.com/tj/commander.js/) for the CLI logic. In `main.js` you can see all of the commands that are added. Each command corresponds to an action in the `src/commands` folder.
104104

105105
The project uses ESM for modules.
106106

107-
#### Action Chains
108-
Commands are generally implemented using action chains. An action chain is a abstraction for combining small pieces of functionality together to accomplish complex logic. An action chain is composed of "links", each link in the chain is a small single purpose function.
109-
110-
The action chain executes each link sequentially. It maintains an `args` object that is passed to each link in the chain, links can modify this args object by returning an object. When a link returns an object that value is spread onto the chains current args object.
111-
112-
Links can halt the chain by explicitly returning `false`. When the chain is halted by a link, no further links in that chain are run. A chain is also halted if a link throws an exception.
113-
114-
Chains can be created using the `createChain` function which takes an array of links. This function returns a new function which executes the chain when invoked.
115-
116-
Here is an example chain:
117-
```js
118-
const exampleChain = createChain([
119-
assertInitialized,
120-
getYear,
121-
getNextUnsolvedPuzzle,
122-
outputPuzzleLink
123-
])
124-
125-
await exampleChain();
126-
```
127-
The chain runs these links in order:
128-
1. `assertInitialized` - Halts the chain if the `cwd` does not contain a user data file.
129-
2. `getYear` - Loads the year from the user data file and adds the year to the chains args.
130-
3. `getNextUnsolvedPuzzle` - Searches the user data file for the first puzzle the user has not solved, the puzzle day and level are added to the chain args.
131-
4. `outputPuzzleLink` - Prints a link to the puzzle in the terminal.
132-
133-
Since the links in a chain are executed sequentially, the order of the links is very important. Some links expect certain args to be present and will fail if those ars are missing. For instance `outputPuzzleLink` requires an args object like `{ year, day, level }`. These fields are added to the args object by the earlier links `getYear` and `getNextUnsolvedPuzzle`.
134-
135107
## Tests
136108
[Jest](https://github.com/facebook/jest) is used for unit testing. There is no set coverage target, but the goal is to have as many quality tests as possible.
137109

@@ -155,13 +127,13 @@ The code is using the [airbnb eslint preset](https://www.npmjs.com/package/eslin
155127

156128
An attempt should be made follow clean coding principles and to match the existing code style and not deviate from the general conventions of the existing code. Consistency is most important.
157129

158-
Some basic non-exhaustive guidelines:
130+
Some basic guidelines:
159131

160132
- Small single purpose methods, decompose large functions into small ones.
161133
- Minimize state, prefer pure functions.
162134
- Minimize coupling.
163135
- Comment public functions with [JSDoc](https://github.com/jsdoc/jsdoc)
164-
- Code should be self documenting, comments should explain the "whys".
136+
- Comments should explain the "whys".
165137
- Prefer descriptive naming and avoid abbreviations (except for common acronyms such as URL or api).
166138
- Prefer latest JS features and async functions.
167139
- Follow rules of thumb

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,6 @@ I am using this CLI for my own advent of code solutions. You can refer to this p
250250
## :bell: Automation Compliance
251251
This CLI does follow the automation guidelines on the /r/adventofcode [community wiki](https://www.reddit.com/r/adventofcode/wiki/faqs/automation/). Specifically:
252252
- Outbound calls are throttled to every five minutes in [rateLimitDecorator.js](https://github.com/beakerandjake/advent-of-code-runner/blob/main/src/api/rateLimitDecorator.js)
253-
- Once inputs are downloaded, they are cached locally in [getPuzzleInput.js](https://github.com/beakerandjake/advent-of-code-runner/blob/main/src/actions/getPuzzleInput.js). If you suspect your input is corrupted, you can manually request a fresh copy by deleting the downloaded file.
253+
- Once inputs are downloaded, they are cached locally in [getPuzzleInput.js](https://github.com/beakerandjake/advent-of-code-runner/blob/main/src/inputs/getPuzzleInput.js). If you suspect your input is corrupted, you can manually request a fresh copy by deleting the downloaded file.
254254
- The User-Agent header in [api.js](https://github.com/beakerandjake/advent-of-code-runner/blob/main/src/api/api.js) is set to `https://github.com/beakerandjake/advent-of-code-runner by beakerandjake`
255-
- Submitted answers are tracked per puzzle and duplicate submissions are prevented in [assertAnswerNotPreviouslySubmitted.js](https://github.com/beakerandjake/advent-of-code-runner/blob/main/src/actions/assertAnswerNotPreviouslySubmitted.js).
255+
- Submitted answers are tracked per puzzle and duplicate submissions are prevented in [submit.js](https://github.com/beakerandjake/advent-of-code-runner/blob/main/src/commands/submit.js).

bin/setupJestExtended.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import { toHaveBeenCalledBefore, toHaveBeenCalledAfter } from 'jest-extended';
2+
expect.extend({ toHaveBeenCalledBefore, toHaveBeenCalledAfter });

scripts/start.js renamed to bin/start.js

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* eslint-disable no-underscore-dangle */
2-
import { argv } from 'node:process';
2+
import { argv, exit } from 'node:process';
33
import { fileURLToPath, URL } from 'node:url';
44
import { join } from 'node:path';
55
import { fork } from 'node:child_process';
@@ -66,7 +66,20 @@ const ensureWorkspaceDir = async () => ensureDir(workspaceDir);
6666
*/
6767
const start = async () => {
6868
await Promise.all([ensureWorkspaceDir(), ensureDotEnv()]);
69-
fork(mainJsPath, argv.slice(2), { cwd: workspaceDir });
69+
return new Promise((resolve, reject) => {
70+
const child = fork(mainJsPath, argv.slice(2), { cwd: workspaceDir });
71+
child.on('exit', (code) => {
72+
if (code === 0) {
73+
resolve();
74+
} else {
75+
reject();
76+
}
77+
});
78+
});
7079
};
7180

72-
await start();
81+
try {
82+
await start();
83+
} catch (error) {
84+
exit(1);
85+
}

jest.config.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ export default {
137137
// setupFiles: [],
138138

139139
// A list of paths to modules that run some code to configure or set up the testing framework before each test
140-
// setupFilesAfterEnv: [],
140+
setupFilesAfterEnv: ["./bin/setupJestExtended.js"],
141141

142142
// The number of seconds after which a test is considered as slow and reported as such in the results.
143143
// slowTestThreshold: 5,

0 commit comments

Comments
 (0)