Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 0 additions & 29 deletions .eslintrc.json

This file was deleted.

44 changes: 44 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: CI

on:
push:
branches: [ main, master ]
pull_request:
branches: [ main, master ]

jobs:
test:
name: Test on Node.js ${{ matrix.node-version }}
runs-on: ubuntu-latest

strategy:
matrix:
node-version: [20.x, 22.x]

steps:
- uses: actions/checkout@v4

- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'

- name: Install dependencies
run: npm ci --legacy-peer-deps

- name: Run linter
run: npm run lint:scripts

- name: Run tests
run: npm test

- name: Build
run: npm run build

- name: Upload coverage
if: matrix.node-version == '20.x'
uses: codecov/codecov-action@v4
continue-on-error: true
with:
fail_ci_if_error: false
35 changes: 35 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: Publish to npm

on:
release:
types: [created]

jobs:
publish:
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write

steps:
- uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20.x'
registry-url: 'https://registry.npmjs.org'

- name: Install dependencies
run: npm ci --legacy-peer-deps

- name: Run tests
run: npm test

- name: Build
run: npm run build

- name: Publish to npm
run: npm publish --access public --provenance
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
44 changes: 44 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.4.0] - 2025-11-15

### Added
- **Generic error type parameter**: You can now specify custom error types for both `attempt` and `attemptPromise`
- Both functions now accept two type parameters: `<T, E = Error>`
- The error type defaults to `Error` for backward compatibility
- Example: `attempt<User, ValidationError>(() => ...)`
- Package metadata:
- `sideEffects: false` for better tree-shaking support
- `engines` field specifying Node.js ^20.19.0 || >=22.12.0

### Changed
- **Major dependency upgrades**:
- ESLint: 8.54.0 → 9.39.1 (migrated to flat config format)
- TypeScript: 5.3.2 → 5.9.3
- Vite: 5.0.2 → 7.2.2
- Vitest: 0.34.6 → 4.0.9
- Prettier: 2.8.8 → 3.6.2
- All other dev dependencies updated to latest versions
- Build tooling:
- Migrated ESLint configuration from `.eslintrc.json` to `eslint.config.js` (flat config)
- Updated package.json exports order (types before import/require)
- Replaced deprecated `@vitest/coverage-c8` with `@vitest/coverage-v8`

### Fixed
- Package.json exports now list types first for better IDE support

## [1.3.9] - Previous release

### Changed
- Type export improvements
- CJS package fixes

## [1.2.x] - Previous releases

### Removed
- `attemptAllPromise` function (caused confusion, may be replaced with better implementation in future)
52 changes: 52 additions & 0 deletions ReadMe.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,58 @@ attemptPromise(fn).then(([error, result]) => {
});
```

### TypeScript Support

As of v1.4.0, you can now type both the result **and** the error with custom types:

#### Basic TypeScript usage

```typescript
import { attempt, attemptPromise } from '@jfdi/attempt';

// Type just the result (error defaults to Error)
const [error, result] = attempt<string>(() => "success");

// Type both result and error
class ValidationError extends Error {
code: number;
}

const [error, result] = attempt<User, ValidationError>(() => {
// your code here
});

// Now TypeScript knows:
// - error is ValidationError | undefined
// - result is User | undefined
```

#### Async with custom error types

```typescript
const [error, data] = await attemptPromise<ApiResponse, ApiError>(
async () => await fetchData()
);

if (error) {
// error is typed as ApiError
console.error(error.statusCode, error.message);
} else {
// data is typed as ApiResponse
console.log(data.results);
}
```

#### Backward compatibility

The error type parameter defaults to `Error`, so existing code continues to work without changes:

```typescript
// These are equivalent:
const [err, res] = attempt<string>(() => "hello");
const [err, res] = attempt<string, Error>(() => "hello");
```

### Examples?

See the tests. They're pretty comprehensive.
Expand Down
46 changes: 46 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import globals from "globals";
import js from "@eslint/js";
import tseslint from "@typescript-eslint/eslint-plugin";
import tsparser from "@typescript-eslint/parser";
import prettierConfig from "eslint-config-prettier";
import prettierPlugin from "eslint-plugin-prettier";

export default [
js.configs.recommended,
{
files: ["**/*.ts", "**/*.js"],
languageOptions: {
ecmaVersion: 2020,
sourceType: "module",
globals: {
...globals.node,
...globals.es6,
Atomics: "readonly",
SharedArrayBuffer: "readonly"
},
parser: tsparser,
parserOptions: {
ecmaVersion: 2020
}
},
plugins: {
"@typescript-eslint": tseslint,
prettier: prettierPlugin
},
rules: {
"prettier/prettier": [
"warn",
{
endOfLine: "auto"
}
],
"no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": "warn",
"no-console": "off",
"no-extra-semi": "warn",
"no-extra-boolean-cast": "warn",
"no-undef": "off" // TypeScript handles this
}
},
prettierConfig
];
Loading
Loading