Skip to content

Commit 7eb631f

Browse files
committed
Require Node.js 18
Fixes #16
1 parent baa71b8 commit 7eb631f

File tree

7 files changed

+90
-65
lines changed

7 files changed

+90
-65
lines changed

.github/workflows/main.yml

+4-4
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ jobs:
1010
fail-fast: false
1111
matrix:
1212
node-version:
13-
- 14
14-
- 12
13+
- 20
14+
- 18
1515
steps:
16-
- uses: actions/checkout@v2
17-
- uses: actions/setup-node@v2
16+
- uses: actions/checkout@v3
17+
- uses: actions/setup-node@v3
1818
with:
1919
node-version: ${{ matrix.node-version }}
2020
- run: npm install

index.d.ts

+18-13
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
import {Options} from 'p-map';
2-
3-
export type PromiseResult<Value> = Value extends PromiseLike<infer Result> ? Result : Value;
1+
import {type Options} from 'p-map';
42

53
export type Mapper<ValueType, KeyType, MappedValueType> = (
64
value: ValueType,
@@ -41,23 +39,30 @@ console.log(await pProps(sites));
4139
// }
4240
```
4341
*/
44-
export default function pProps<
45-
KeyType,
46-
ValueType,
47-
MappedValueType = PromiseResult<ValueType>
42+
export default function pProps< // This overload exists to get more accurate results when the mapper is not defined.
43+
InputType extends Record<PropertyKey, unknown>,
4844
>(
49-
map: ReadonlyMap<KeyType, ValueType>,
50-
mapper?: Mapper<PromiseResult<ValueType>, KeyType, MappedValueType>,
45+
map: InputType,
46+
mapper?: undefined,
5147
options?: Options
52-
): Promise<Map<KeyType, MappedValueType>>;
48+
): Promise<{[key in keyof InputType]: Awaited<InputType[key]>}>;
5349
export default function pProps<
54-
InputType extends Record<string, any>,
50+
InputType extends Record<string, unknown>,
5551
ValueType extends InputType[keyof InputType],
56-
MappedValueType = PromiseResult<ValueType>
52+
MappedValueType = Awaited<ValueType>,
5753
>(
5854
map: InputType,
59-
mapper?: Mapper<PromiseResult<ValueType>, keyof InputType, MappedValueType>,
55+
mapper?: Mapper<Awaited<ValueType>, keyof InputType, MappedValueType>,
6056
options?: Options
6157
): Promise<{[key in keyof InputType]: MappedValueType}>;
58+
export default function pProps<
59+
KeyType,
60+
ValueType,
61+
MappedValueType = Awaited<ValueType>,
62+
>(
63+
map: ReadonlyMap<KeyType, ValueType>,
64+
mapper?: Mapper<Awaited<ValueType>, KeyType, MappedValueType>,
65+
options?: Options
66+
): Promise<Map<KeyType, MappedValueType>>;
6267

6368
export {Options} from 'p-map';

index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import pMap from 'p-map';
22

33
export default async function pProps(input, mapper = (value => value), options = undefined) {
44
const isMap = input instanceof Map;
5-
const entries = isMap ? [...input.entries()] : Object.entries(input);
5+
const entries = isMap ? [...input] : Object.entries(input);
66
const values = await pMap(entries, async ([key, value]) => mapper(await value, key), options);
77
const mappedEntries = entries.map(([key], index) => [key, values[index]]);
88
return isMap ? new Map(mappedEntries) : Object.fromEntries(mappedEntries);

index.test-d.ts

+41-24
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,83 @@
11
import {expectType, expectAssignable} from 'tsd';
2-
import pProps, {Options} from './index.js';
2+
import pProps, {type Options} from './index.js';
33

4-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
54
const options: Options = {};
65

76
expectType<Promise<{[key in 'foo']: string}>>(pProps({foo: 'bar'}));
87
expectType<Promise<{[key in 'foo']: boolean}>>(
9-
pProps({foo: 'bar'}, (value, key) => {
8+
pProps({foo: 'bar'}, async (value, key) => {
109
expectType<string>(value);
1110
expectType<'foo'>(key);
1211
return Math.random() > 0.5 ? false : Promise.resolve(true);
13-
})
12+
}),
1413
);
1514
expectType<Promise<{[key in 'foo']: boolean}>>(
1615
pProps(
1716
{foo: 'bar'},
18-
(value, key) => {
17+
async (value, key) => {
1918
expectType<string>(value);
2019
expectType<'foo'>(key);
2120
return Math.random() > 0.5 ? false : Promise.resolve(true);
2221
},
2322
{
24-
concurrency: 1
25-
}
26-
)
23+
concurrency: 1,
24+
},
25+
),
2726
);
2827

2928
const hashMap = {
3029
unicorn: Promise.resolve(1),
31-
foo: 'bar'
30+
foo: 'bar',
3231
};
3332

34-
expectType<Promise<{[key in 'unicorn' | 'foo']: string | number}>>(
35-
pProps(hashMap)
33+
// TODO: Should ideally be:
34+
// expectType<Promise<{unicorn: 1; foo: 'bar'}>>(
35+
expectType<Promise<{unicorn: number; foo: string}>>(
36+
pProps(hashMap),
37+
);
38+
39+
const hashMap2 = {
40+
unicorn: Promise.resolve(1),
41+
foo: 'bar',
42+
} as const;
43+
44+
// TODO: Should ideally be:
45+
// expectType<Promise<{readonly unicorn: 1; readonly foo: 'bar'}>>(
46+
expectType<Promise<{readonly unicorn: number; readonly foo: 'bar'}>>(
47+
pProps(hashMap2),
3648
);
49+
50+
expectType<{bar: 'baz'; thud: 'qux'}>(
51+
await pProps({bar: 'baz' as const, thud: 'qux' as const}),
52+
);
53+
3754
expectType<Promise<{[key in 'unicorn' | 'foo']: boolean}>>(
38-
pProps(hashMap, (value, key) => {
55+
pProps(hashMap, async (value, key) => {
3956
expectType<string | number>(value);
4057
expectAssignable<string>(key);
4158
return Math.random() > 0.5 ? false : Promise.resolve(true);
42-
})
59+
}),
4360
);
4461
expectType<Promise<{[key in 'unicorn' | 'foo']: boolean}>>(
4562
pProps(
4663
hashMap,
47-
(value, key) => {
64+
async (value, key) => {
4865
expectType<string | number>(value);
4966
expectAssignable<string>(key);
5067
return Math.random() > 0.5 ? false : Promise.resolve(true);
5168
},
5269
{
53-
concurrency: 1
54-
}
55-
)
70+
concurrency: 1,
71+
},
72+
),
5673
);
5774

5875
const partialMap: {foo?: Promise<string>} = {};
5976
expectType<Promise<{foo?: string}>>(pProps(partialMap));
6077

6178
const map = new Map<number, string | Promise<string>>([
6279
[1, Promise.resolve('1')],
63-
[2, '2']
80+
[2, '2'],
6481
]);
6582

6683
const result = await pProps(map);
@@ -69,22 +86,22 @@ expectType<string | undefined>(result.get(1));
6986

7087
expectType<Promise<Map<number, string>>>(pProps(map));
7188
expectType<Promise<Map<number, number>>>(
72-
pProps(map, (value, key) => {
89+
pProps(map, async (value, key) => {
7390
expectType<string>(value);
7491
expectType<number>(key);
7592
return Math.random() > 0.5 ? 1 : Promise.resolve(2);
76-
})
93+
}),
7794
);
7895
expectType<Promise<Map<number, number>>>(
7996
pProps(
8097
map,
81-
(value, key) => {
98+
async (value, key) => {
8299
expectType<string>(value);
83100
expectType<number>(key);
84101
return Math.random() > 0.5 ? 1 : Promise.resolve(2);
85102
},
86103
{
87-
concurrency: 1
88-
}
89-
)
104+
concurrency: 1,
105+
},
106+
),
90107
);

package.json

+10-7
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,12 @@
1111
"url": "https://sindresorhus.com"
1212
},
1313
"type": "module",
14-
"exports": "./index.js",
14+
"exports": {
15+
"types": "./index.d.ts",
16+
"default": "./index.js"
17+
},
1518
"engines": {
16-
"node": ">=12.20"
19+
"node": ">=18"
1720
},
1821
"scripts": {
1922
"test": "xo && ava && tsd"
@@ -39,12 +42,12 @@
3942
"bluebird"
4043
],
4144
"dependencies": {
42-
"p-map": "^5.0.0"
45+
"p-map": "^6.0.0"
4346
},
4447
"devDependencies": {
45-
"ava": "^3.15.0",
46-
"delay": "^5.0.0",
47-
"tsd": "^0.17.0",
48-
"xo": "^0.40.2"
48+
"ava": "^5.3.1",
49+
"delay": "^6.0.0",
50+
"tsd": "^0.29.0",
51+
"xo": "^0.56.0"
4952
}
5053
}

readme.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ Useful when you need to run multiple promises concurrently and keep track of the
66

77
## Install
88

9-
```
10-
$ npm install p-props
9+
```sh
10+
npm install p-props
1111
```
1212

1313
## Usage

test.js

+14-14
Original file line numberDiff line numberDiff line change
@@ -7,36 +7,36 @@ test('main', async t => {
77
await pProps({
88
foo: delay(100).then(() => 1),
99
bar: Promise.resolve(2),
10-
faz: 3
10+
faz: 3,
1111
}),
1212
{
1313
foo: 1,
1414
bar: 2,
15-
faz: 3
16-
}
15+
faz: 3,
16+
},
1717
);
1818
});
1919

2020
test('`Map` input', async t => {
2121
t.deepEqual(
2222
await pProps(new Map([
2323
['foo', Promise.resolve(1)],
24-
['bar', 2]
24+
['bar', 2],
2525
])),
2626
new Map([
2727
['foo', 1],
28-
['bar', 2]
29-
])
28+
['bar', 2],
29+
]),
3030
);
3131
});
3232

3333
test('rejects if any of the input promises reject', async t => {
3434
await t.throwsAsync(
3535
pProps({
3636
foo: Promise.resolve(1),
37-
bar: Promise.reject(new Error('bar'))
37+
bar: Promise.reject(new Error('bar')),
3838
}),
39-
{message: 'bar'}
39+
{message: 'bar'},
4040
);
4141
});
4242

@@ -51,7 +51,7 @@ test('with mapper', async t => {
5151
t.deepEqual(
5252
await pProps({
5353
foo: 1,
54-
baz: Promise.resolve(2)
54+
baz: Promise.resolve(2),
5555
}, async (value, key) => {
5656
if (key === 'foo') {
5757
t.is(value, 1);
@@ -65,8 +65,8 @@ test('with mapper', async t => {
6565
}),
6666
{
6767
foo: 'foo1',
68-
baz: 'baz2'
69-
}
68+
baz: 'baz2',
69+
},
7070
);
7171
});
7272

@@ -76,7 +76,7 @@ test('`Map` input with mapper', async t => {
7676
t.deepEqual(
7777
await pProps(new Map([
7878
['foo', 1],
79-
['bar', Promise.resolve(2)]
79+
['bar', Promise.resolve(2)],
8080
]), async (value, key) => {
8181
if (key === 'foo') {
8282
t.is(value, 1);
@@ -90,7 +90,7 @@ test('`Map` input with mapper', async t => {
9090
}),
9191
new Map([
9292
['foo', 'foo1'],
93-
['bar', 'bar2']
94-
])
93+
['bar', 'bar2'],
94+
]),
9595
);
9696
});

0 commit comments

Comments
 (0)