-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
26 changed files
with
8,947 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
# https://editorconfig.org/ | ||
# https://prettier.io/docs/en/configuration.html#editorconfig | ||
|
||
root = true | ||
|
||
[*] | ||
charset = utf-8 | ||
end_of_line = lf | ||
indent_size = 2 | ||
indent_style = space | ||
insert_final_newline = true | ||
trim_trailing_whitespace = true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/build |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
module.exports = { | ||
root: true, | ||
parser: "@typescript-eslint/parser", | ||
plugins: ["@typescript-eslint", "unused-imports"], | ||
extends: [ | ||
"eslint:recommended", | ||
"plugin:@typescript-eslint/recommended", | ||
"prettier", | ||
], | ||
env: { | ||
node: true, | ||
}, | ||
overrides: [ | ||
{ | ||
files: ["**/*.ts?(x)"], | ||
parserOptions: { | ||
project: ["./tsconfig.json"], | ||
tsconfigRootDir: __dirname, | ||
}, | ||
extends: [ | ||
"eslint:recommended", | ||
"plugin:@typescript-eslint/recommended", | ||
"plugin:@typescript-eslint/recommended-requiring-type-checking", | ||
"prettier", | ||
], | ||
rules: { | ||
"@typescript-eslint/no-shadow": "warn", | ||
"@typescript-eslint/no-unsafe-argument": "warn", | ||
"@typescript-eslint/no-unsafe-assignment": "warn", | ||
"@typescript-eslint/no-unsafe-call": "warn", | ||
"@typescript-eslint/no-unsafe-member-access": "warn", | ||
"@typescript-eslint/no-unsafe-return": "warn", | ||
"unused-imports/no-unused-imports": "error", | ||
curly: "error", | ||
}, | ||
}, | ||
{ | ||
files: ["**/__tests__/**/*.[jt]s?(x)", "**/?(*.)+(test).[jt]s?(x)"], | ||
rules: { | ||
"@typescript-eslint/no-unsafe-member-access": "off", | ||
"@typescript-eslint/no-unsafe-return": "off", | ||
"@typescript-eslint/no-unsafe-argument": "off", | ||
"@typescript-eslint/no-explicit-any": "off", | ||
"@typescript-eslint/unbound-method": "off", | ||
}, | ||
}, | ||
], | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
name: ci | ||
on: | ||
pull_request: | ||
push: | ||
branches: [main] | ||
concurrency: | ||
group: ${{ github.workflow }}-${{ github.ref }} | ||
cancel-in-progress: true | ||
jobs: | ||
lint-and-typecheck: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- uses: actions/setup-node@v4 | ||
with: | ||
node-version-file: ".nvmrc" | ||
cache: "npm" | ||
- name: Cache node_modules/.cache directory | ||
uses: actions/cache@v4 | ||
with: | ||
path: node_modules/.cache | ||
key: node-modules-dot-cache-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}-${{ github.run_id }} | ||
restore-keys: | | ||
node-modules-dot-cache-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}- | ||
- run: npm ci --prefer-offline --no-audit | ||
- run: npm run prettier | ||
- run: npx tsc --noEmit | ||
- run: npm run test:ci | ||
- run: npm run eslint |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# Compiled code | ||
build/ | ||
|
||
# Dependency directories | ||
node_modules/ | ||
|
||
# TypeScript cache | ||
*.tsbuildinfo | ||
|
||
# npm cache directory | ||
.npm | ||
|
||
# eslint cache | ||
.eslintcache |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
18 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
.github/*.md | ||
.vscode | ||
build |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
{} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"recommendations": [ | ||
"editorconfig.editorconfig", | ||
"dbaeumer.vscode-eslint", | ||
"esbenp.prettier-vscode" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"cSpell.words": [ | ||
"fieldguide" | ||
], | ||
"typescript.tsdk": "node_modules/typescript/lib", | ||
"editor.defaultFormatter": "esbenp.prettier-vscode" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
MIT License | ||
|
||
Copyright (c) 2024 Fieldguide | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,122 @@ | ||
# pipeline | ||
A toolkit to easily build synchronous process pipelines in TypeScript/JavaScript | ||
# Pipeline | ||
|
||
A type-safe toolkit to easily compose synchronous process chains in TypeScript/JavaScript | ||
|
||
## Table of Contents | ||
|
||
- [Table of Contents](#table-of-contents) | ||
- [Overview](#overview) | ||
- [Installation](#installation) | ||
- [Types](#types) | ||
- [Builder](#builder) | ||
- [Initializer](#initializer) | ||
- [Stages](#stages) | ||
- [Stage Arguments](#stage-arguments) | ||
- [Stage Results](#stage-results) | ||
- [Results Validator](#results-validator) | ||
- [Middleware](#middleware) | ||
- [Error Handling](#error-handling) | ||
- [Example Use Cases](#example-use-cases) | ||
|
||
## Overview | ||
|
||
This library seeks to provide a structure to break down large multi-step process chains in order to make them composable and testable. | ||
|
||
 | ||
|
||
## Installation | ||
|
||
Install the package with your favorite package manager: | ||
|
||
``` | ||
npm install @fieldguide/pipeline | ||
``` | ||
|
||
## Types | ||
|
||
There are three core types to consider when constructing and using a pipeline: | ||
|
||
1. **Arguments** represent the data that gets passed into the pipeline at runtime | ||
2. **Context** represents the internal data that is shared with each pipeline stage | ||
3. **Results** represent the data that is output from a pipeline execution | ||
|
||
It is common to see these types abbreviated as `A`, `C`, and `R` respectively. | ||
|
||
## Builder | ||
|
||
The [pipeline builder](./src/buildPipeline.ts) is a factory that accepts the individual pieces of a pipeline and constructs a single callable of the `Pipeline` type: | ||
|
||
```typescript | ||
export type Pipeline<A extends object, R extends object> = ( | ||
args: A, | ||
) => Promise<R>; | ||
``` | ||
|
||
Notice that the callable takes a single arguments object (`A`) and outputs a promise representing the results object (`R`). The execution context (`C`) is internal to the pipeline stages, so it is not represented in the pipeline callable constructed by the builder. | ||
|
||
## Initializer | ||
|
||
The **Initializer** is a method that takes in the pipeline's arguments and produces a Context object. The context is then passed as an argument into each stage. | ||
|
||
> [!NOTE] | ||
> The initializer should create the "empty state" of the context object. It is recommended to initialize empty arrays, sets, maps, and objects within the initializer that stages can add data to or manipulate later. | ||
## Stages | ||
|
||
**Stages** are the independent steps in the process chain. They are processed synchronously (one at a time, in order) until the end of the chain is reached. | ||
|
||
### Stage Arguments | ||
|
||
The following arguments are provided to a stage when it is executed: | ||
|
||
| Argument | Description | | ||
| ---------- | ------------------------------------------------------------------------------------------------------------------ | | ||
| `context` | The execution context object setup by the initializer and manipulated by any previous stages | | ||
| `metadata` | The name of the pipeline (helpful for logging/metrics) and the initial arguments provided to the pipeline callable | | ||
|
||
### Stage Results | ||
|
||
Each stage can return a partial results object for the pipeline. These results are collected and merged as each stage is processed. If a later stage specifies the same key in the results object as an earlier stage, the later stage's result will overwrite the earlier result. | ||
|
||
## Results Validator | ||
|
||
The **Results Validator** ensures that the pipeline has fulfilled the interface specified for its result. Since each stage returns a _partial_ result set, this method verifies that the entire result has been supplied. | ||
|
||
## Middleware | ||
|
||
If **Middleware** is specified, it will be run on the specified stage lifecycle event(s) for each stage in the pipeline. | ||
|
||
| Stage Event | Description | | ||
| ----------------- | ---------------------------------- | | ||
| `onStageStart` | Runs before each stage is executed | | ||
| `onStageComplete` | Runs after each stage is executed | | ||
|
||
Middleware is specified as an object with middleware callbacks mapped to at least one of the above event keys. A middleware callback is provided the following attributes: | ||
|
||
| Parameter | Description | | ||
| -------------- | ----------------------------------------------------------------------------- | | ||
| `context` | The pipeline execution context object | | ||
| `metadata` | The pipeline's metadata (name and runtime arguments) | | ||
| `results` | A read-only set of results returned by stages so far | | ||
| `stageNames` | An array of the names of the methods that make up the current pipeline stages | | ||
| `currentStage` | The name of the current pipeline stage | | ||
|
||
See the [LogStageMiddlewareFactory](./src/middleware/logStageMiddlewareFactory.ts) for a simple middleware implementation. It is wrapped in a factory method so a log method can be properly injected. | ||
|
||
```typescript | ||
buildPipeline({ | ||
/* ... */ | ||
middleware: [logStageMiddlewareFactory(logger.log)], | ||
/* ... */ | ||
}); | ||
``` | ||
|
||
## Error Handling | ||
|
||
When an error occurs during pipeline execution, an instance of [PipelineError](./src/error/PipelineError.ts) is thrown. | ||
|
||
In order to decorate or extend pipeline error handling, use a standard try/catch block around pipeline invocation. | ||
|
||
## Example Use Cases | ||
|
||
1. [Data Export Pipeline](./docs/cases/data-export-pipeline.md) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
module.exports = { | ||
presets: [ | ||
["@babel/preset-env", { targets: { node: "current" } }], | ||
"@babel/preset-typescript", | ||
], | ||
}; |
Oops, something went wrong.