Skip to content

Commit

Permalink
feat: add goGenerator, goAsyncGenerator
Browse files Browse the repository at this point in the history
BREAKING CHANGE:
- It requires Node.js >= v18.17.0
- CommonJS => ESM
  • Loading branch information
BlackGlory committed Apr 17, 2024
1 parent 209bb79 commit d135630
Show file tree
Hide file tree
Showing 18 changed files with 1,857 additions and 3,075 deletions.
6 changes: 0 additions & 6 deletions .eslintignore

This file was deleted.

17 changes: 0 additions & 17 deletions .eslintrc.js

This file was deleted.

2 changes: 1 addition & 1 deletion .github/workflows/nodejs.yml
Expand Up @@ -9,7 +9,7 @@ jobs:

strategy:
matrix:
node-version: [14.x, 16.x]
node-version: [18.x]

steps:
- uses: actions/checkout@v2
Expand Down
76 changes: 76 additions & 0 deletions __tests__/go-async-generator.spec.ts
@@ -0,0 +1,76 @@
import { describe, test, expect, vi } from 'vitest'
import { goAsyncGenerator } from '@src/go-async-generator.js'
import { getErrorAsync } from 'return-style'
import { toArrayAsync } from 'iterable-operator'

describe('goAsyncGenerator', () => {
describe('non-generator', () => {
test('return value', async () => {
const fn = vi.fn()

await toArrayAsync(goAsyncGenerator(fn))

expect(fn).toBeCalledTimes(1)
})

test('throw error', async () => {
const fn = vi.fn(() => {
throw new Error('foo')
})

const err = await getErrorAsync(() => toArrayAsync(goAsyncGenerator(fn)))

expect(err).toBeInstanceOf(Error)
expect(err?.message).toBe('foo')
expect(fn).toBeCalledTimes(1)
})
})

describe('generator', () => {
test('yield value', async () => {
const fn = vi.fn(function* () {
yield
})

await toArrayAsync(goAsyncGenerator(fn))

expect(fn).toBeCalledTimes(1)
})

test('throw error', async () => {
const fn = vi.fn(function* () {
throw new Error('foo')
})

const err = await getErrorAsync(() => toArrayAsync(goAsyncGenerator(fn)))

expect(err).toBeInstanceOf(Error)
expect(err?.message).toBe('foo')
expect(fn).toBeCalledTimes(1)
})
})

describe('async generator', () => {
test('yield value', async () => {
const fn = vi.fn(async function* () {
yield
})

await toArrayAsync(goAsyncGenerator(fn))

expect(fn).toBeCalledTimes(1)
})

test('throw error', async () => {
const fn = vi.fn(async function* () {
throw new Error('foo')
})

const err = await getErrorAsync(() => toArrayAsync(goAsyncGenerator(fn)))

expect(err).toBeInstanceOf(Error)
expect(err?.message).toBe('foo')
expect(fn).toBeCalledTimes(1)
})
})
})
52 changes: 52 additions & 0 deletions __tests__/go-generator.spec.ts
@@ -0,0 +1,52 @@
import { describe, test, expect, vi } from 'vitest'
import { goGenerator } from '@src/go-generator.js'
import { getError } from 'return-style'
import { toArray } from 'iterable-operator'

describe('goGenerator', () => {
describe('non-generator', () => {
test('return value', () => {
const fn = vi.fn()

toArray(goGenerator(fn))

expect(fn).toBeCalledTimes(1)
})

test('throw error', () => {
const fn = vi.fn(() => {
throw new Error('foo')
})

const err = getError(() => toArray(goGenerator(fn)))

expect(err).toBeInstanceOf(Error)
expect(err?.message).toBe('foo')
expect(fn).toBeCalledTimes(1)
})
})

describe('generator', () => {
test('yield value', () => {
const fn = vi.fn(function* () {
yield
})

toArray(goGenerator(fn))

expect(fn).toBeCalledTimes(1)
})

test('throw error', () => {
const fn = vi.fn(function* () {
throw new Error('foo')
})

const err = getError(() => toArray(goGenerator(fn)))

expect(err).toBeInstanceOf(Error)
expect(err?.message).toBe('foo')
expect(fn).toBeCalledTimes(1)
})
})
})
11 changes: 6 additions & 5 deletions __tests__/go-macrotask.spec.ts
@@ -1,11 +1,12 @@
import { goMacrotask } from '@src/go-macrotask'
import { describe, test, expect, vi } from 'vitest'
import { goMacrotask } from '@src/go-macrotask.js'
import { getErrorPromise } from 'return-style'

describe('goMacrotask', () => {
describe('sync', () => {
test('return value', async () => {
let count = 0
const fn = jest.fn(() => ++count)
const fn = vi.fn(() => ++count)

const promise = goMacrotask(fn)
queueMicrotask(() => count++)
Expand All @@ -16,7 +17,7 @@ describe('goMacrotask', () => {
})

test('throw error', async () => {
const fn = jest.fn(() => {
const fn = vi.fn(() => {
throw new Error('foo')
})

Expand All @@ -32,7 +33,7 @@ describe('goMacrotask', () => {
describe('async', () => {
test('resolved', async () => {
let count = 0
const fn = jest.fn(async () => ++count)
const fn = vi.fn(async () => ++count)

const promise = goMacrotask(fn)
queueMicrotask(() => count++)
Expand All @@ -43,7 +44,7 @@ describe('goMacrotask', () => {
})

test('rejected', async () => {
const fn = jest.fn().mockRejectedValue(new Error('foo'))
const fn = vi.fn().mockRejectedValue(new Error('foo'))

const promise = goMacrotask(fn)
const err = await getErrorPromise(promise)
Expand Down
11 changes: 6 additions & 5 deletions __tests__/go-microtask.spec.ts
@@ -1,11 +1,12 @@
import { goMicrotask } from '@src/go-microtask'
import { describe, test, expect, vi } from 'vitest'
import { goMicrotask } from '@src/go-microtask.js'
import { getErrorPromise } from 'return-style'

describe('goMicrotask', () => {
describe('sync', () => {
test('return value', async () => {
let count = 0
const fn = jest.fn(() => ++count)
const fn = vi.fn(() => ++count)

const promise = goMicrotask(fn)
queueMicrotask(() => count++)
Expand All @@ -16,7 +17,7 @@ describe('goMicrotask', () => {
})

test('throw error', async () => {
const fn = jest.fn(() => {
const fn = vi.fn(() => {
throw new Error('foo')
})

Expand All @@ -32,7 +33,7 @@ describe('goMicrotask', () => {
describe('async', () => {
test('resolved', async () => {
let count = 0
const fn = jest.fn(async () => ++count)
const fn = vi.fn(async () => ++count)

const promise = goMicrotask(fn)
queueMicrotask(() => count++)
Expand All @@ -43,7 +44,7 @@ describe('goMicrotask', () => {
})

test('rejected', async () => {
const fn = jest.fn().mockRejectedValue(new Error('foo'))
const fn = vi.fn().mockRejectedValue(new Error('foo'))

const promise = goMicrotask(fn)
const err = await getErrorPromise(promise)
Expand Down
11 changes: 6 additions & 5 deletions __tests__/go.spec.ts
@@ -1,10 +1,11 @@
import { go } from '@src/go'
import { describe, test, expect, vi } from 'vitest'
import { go } from '@src/go.js'
import { getError, getErrorPromise } from 'return-style'

describe('go', () => {
describe('sync', () => {
test('return value', () => {
const fn = jest.fn().mockReturnValue('foo')
const fn = vi.fn().mockReturnValue('foo')

const result = go(fn)

Expand All @@ -13,7 +14,7 @@ describe('go', () => {
})

test('throw error', () => {
const fn = jest.fn(() => {
const fn = vi.fn(() => {
throw new Error('foo')
})

Expand All @@ -28,7 +29,7 @@ describe('go', () => {
describe('async', () => {
test('resolved', async () => {
let count = 0
const fn = jest.fn(async () => ++count)
const fn = vi.fn(async () => ++count)

const promise = go(fn)
queueMicrotask(() => count++)
Expand All @@ -39,7 +40,7 @@ describe('go', () => {
})

test('rejected', async () => {
const fn = jest.fn().mockRejectedValue(new Error('foo'))
const fn = vi.fn().mockRejectedValue(new Error('foo'))

const promise = go(fn)
const err = await getErrorPromise(promise)
Expand Down
File renamed without changes.
14 changes: 14 additions & 0 deletions eslint.config.js
@@ -0,0 +1,14 @@
// @ts-check

import js from '@eslint/js'
import ts from 'typescript-eslint'

export default ts.config(
js.configs.recommended
, ...ts.configs.recommended
, {
rules: {
'require-yield': 'off'
}
}
)
11 changes: 0 additions & 11 deletions jest.config.js

This file was deleted.

50 changes: 27 additions & 23 deletions package.json
Expand Up @@ -12,44 +12,48 @@
"repository": "git@github.com:BlackGlory/go.git",
"author": "BlackGlory <woshenmedoubuzhidao@blackglory.me>",
"license": "MIT",
"type": "module",
"sideEffects": false,
"engines": {
"node": ">=18.17.0"
},
"scripts": {
"lint": "eslint --ext .js,.jsx,.ts,.tsx --quiet src",
"test": "jest --config jest.config.js",
"test:coverage": "jest --coverage --config jest.config.js",
"prepublishOnly": "run-s clean build",
"prepare": "ts-patch install -s",
"lint": "eslint --quiet src __tests__",
"test": "vitest --run",
"prepublishOnly": "run-s prepare clean build",
"clean": "rimraf lib",
"build": "run-s build:*",
"build:compile": "tsc --project tsconfig.build.json --module commonjs --target es2018 --outDir lib",
"build:patch": "tscpaths -p tsconfig.build.json -s ./src -o ./lib",
"build": "tsc --project tsconfig.build.json --outDir lib",
"release": "standard-version"
},
"husky": {
"hooks": {
"pre-commit": "run-s lint build test",
"pre-commit": "run-s prepare lint build test",
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
}
},
"devDependencies": {
"@commitlint/cli": "^17.0.2",
"@commitlint/config-conventional": "^17.0.2",
"@types/jest": "^28.1.1",
"@typescript-eslint/eslint-plugin": "^5.27.1",
"@typescript-eslint/parser": "^5.27.1",
"eslint": "^8.17.0",
"@commitlint/cli": "^19.2.2",
"@commitlint/config-conventional": "^19.2.2",
"@eslint/js": "^9.0.0",
"eslint": "^9.0.0",
"husky": "4",
"jest": "^28.1.1",
"iterable-operator": "^5.0.0",
"npm-run-all": "^4.1.5",
"return-style": "^1.0.0",
"rimraf": "^3.0.2",
"return-style": "^3.0.1",
"rimraf": "^5.0.5",
"standard-version": "^9.5.0",
"ts-jest": "^28.0.4",
"tscpaths": "^0.0.9",
"tslib": "^2.4.0",
"typescript": "^4.7.3"
"ts-patch": "^3.1.2",
"tslib": "^2.6.2",
"typescript": "^5.4.5",
"typescript-eslint": "^7.7.0",
"typescript-transform-paths": "^3.4.7",
"vite": "^5.2.9",
"vite-tsconfig-paths": "^4.3.2",
"vitest": "^1.5.0"
},
"dependencies": {
"extra-timers": "^0.2.5",
"justypes": "^2.0.0"
"extra-timers": "^0.2.6",
"justypes": "^4.2.1"
}
}
11 changes: 11 additions & 0 deletions src/go-async-generator.ts
@@ -0,0 +1,11 @@
export async function* goAsyncGenerator<Yield, Next>(
fn: () =>
| void
| Generator<Yield, void, Next>
| AsyncGenerator<Yield, void, Next>
): AsyncGenerator<Yield, void, Next> {
const generator = fn()
if (generator) {
yield* generator
}
}

0 comments on commit d135630

Please sign in to comment.