Skip to content

Commit 2dc333e

Browse files
committed
Require Node.js 12.20 and move to ESM
1 parent 4a628f9 commit 2dc333e

File tree

8 files changed

+167
-182
lines changed

8 files changed

+167
-182
lines changed

.github/workflows/main.yml

+2-5
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,10 @@ jobs:
1010
fail-fast: false
1111
matrix:
1212
node-version:
13-
- 14
14-
- 12
15-
- 10
16-
- 8
13+
- 16
1714
steps:
1815
- uses: actions/checkout@v2
19-
- uses: actions/setup-node@v1
16+
- uses: actions/setup-node@v2
2017
with:
2118
node-version: ${{ matrix.node-version }}
2219
- run: npm install

index.d.ts

+62-66
Original file line numberDiff line numberDiff line change
@@ -1,81 +1,77 @@
1-
declare namespace writeJsonFile {
2-
type Replacer = (this: unknown, key: string, value: any) => unknown;
3-
type SortKeys = (a: string, b: string) => number;
1+
export type Replacer = (this: unknown, key: string, value: unknown) => unknown;
2+
export type SortKeys = (a: string, b: string) => number;
43

5-
interface Options {
6-
/**
7-
Indentation as a string or number of spaces. Pass in `undefined` for no formatting.
8-
9-
@default '\t'
10-
*/
11-
readonly indent?: string | number | undefined;
12-
13-
/**
14-
Detect indentation automatically if the file exists.
15-
16-
@default false
17-
*/
18-
readonly detectIndent?: boolean;
19-
20-
/**
21-
Sort the keys recursively. Optionally pass in a compare function.
4+
export interface Options {
5+
/**
6+
Indentation as a string or number of spaces.
227
23-
@default false
24-
*/
25-
readonly sortKeys?: boolean | SortKeys;
8+
Pass in `undefined` for no formatting.
269
27-
/**
28-
Passed into `JSON.stringify`.
29-
*/
30-
readonly replacer?: Replacer | ReadonlyArray<number | string>;
10+
@default '\t'
11+
*/
12+
readonly indent?: string | number | undefined;
3113

32-
/**
33-
Mode used when writing the file.
14+
/**
15+
Detect indentation automatically if the file exists.
3416
35-
@default 0o666
36-
*/
37-
readonly mode?: number;
38-
}
39-
}
17+
@default false
18+
*/
19+
readonly detectIndent?: boolean;
4020

41-
declare const writeJsonFile: {
4221
/**
43-
Stringify and write JSON to a file atomically.
44-
45-
Creates directories for you as needed.
22+
Sort the keys recursively.
4623
47-
@example
48-
```
49-
import writeJsonFile = require('write-json-file');
24+
Optionally pass in a compare function.
5025
51-
(async () => {
52-
await writeJsonFile('foo.json', {foo: true});
53-
})();
54-
```
26+
@default false
5527
*/
56-
(
57-
filePath: string,
58-
data: unknown,
59-
options?: writeJsonFile.Options
60-
): Promise<void>;
28+
readonly sortKeys?: boolean | SortKeys;
6129

6230
/**
63-
Stringify and write JSON to a file atomically.
64-
65-
Creates directories for you as needed.
31+
Passed into `JSON.stringify`.
32+
*/
33+
readonly replacer?: Replacer | ReadonlyArray<number | string>;
6634

67-
@example
68-
```
69-
import writeJsonFile = require('write-json-file');
35+
/**
36+
The mode used when writing the file.
7037
71-
writeJsonFile.sync('foo.json', {foo: true});
72-
```
38+
@default 0o666
7339
*/
74-
sync(
75-
filePath: string,
76-
data: unknown,
77-
options?: writeJsonFile.Options
78-
): void;
79-
};
80-
81-
export = writeJsonFile;
40+
readonly mode?: number;
41+
}
42+
43+
/**
44+
Stringify and write JSON to a file atomically.
45+
46+
Creates directories for you as needed.
47+
48+
@example
49+
```
50+
import {writeJsonFile} from 'write-json-file';
51+
52+
await writeJsonFile('foo.json', {foo: true});
53+
```
54+
*/
55+
export function writeJsonFile(
56+
filePath: string,
57+
data: unknown,
58+
options?: Options
59+
): Promise<void>;
60+
61+
/**
62+
Stringify and write JSON to a file atomically.
63+
64+
Creates directories for you as needed.
65+
66+
@example
67+
```
68+
import {writeJsonFileSync} from 'write-json-file';
69+
70+
writeJsonFileSync('foo.json', {foo: true});
71+
```
72+
*/
73+
export function writeJsonFileSync(
74+
filePath: string,
75+
data: unknown,
76+
options?: Options
77+
): void;

index.js

+19-24
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,11 @@
1-
'use strict';
2-
const {promisify} = require('util');
3-
const path = require('path');
4-
const fs = require('graceful-fs');
5-
const writeFileAtomic = require('write-file-atomic');
6-
const sortKeys = require('sort-keys');
7-
const makeDir = require('make-dir');
8-
const detectIndent = require('detect-indent');
9-
const isPlainObj = require('is-plain-obj');
10-
11-
const readFile = promisify(fs.readFile);
12-
13-
const init = (fn, filePath, data, options) => {
1+
import path from 'node:path';
2+
import fs, {promises as fsPromises} from 'node:fs';
3+
import writeFileAtomic from 'write-file-atomic';
4+
import sortKeys from 'sort-keys';
5+
import detectIndent from 'detect-indent';
6+
import isPlainObj from 'is-plain-obj';
7+
8+
const init = (function_, filePath, data, options) => {
149
if (!filePath) {
1510
throw new TypeError('Expected a filepath');
1611
}
@@ -22,24 +17,24 @@ const init = (fn, filePath, data, options) => {
2217
options = {
2318
indent: '\t',
2419
sortKeys: false,
25-
...options
20+
...options,
2621
};
2722

2823
if (options.sortKeys && isPlainObj(data)) {
2924
data = sortKeys(data, {
3025
deep: true,
31-
compare: typeof options.sortKeys === 'function' ? options.sortKeys : undefined
26+
compare: typeof options.sortKeys === 'function' ? options.sortKeys : undefined,
3227
});
3328
}
3429

35-
return fn(filePath, data, options);
30+
return function_(filePath, data, options);
3631
};
3732

3833
const main = async (filePath, data, options) => {
3934
let {indent} = options;
4035
let trailingNewline = '\n';
4136
try {
42-
const file = await readFile(filePath, 'utf8');
37+
const file = await fsPromises.readFile(filePath, 'utf8');
4338
if (!file.endsWith('\n')) {
4439
trailingNewline = '';
4540
}
@@ -81,12 +76,12 @@ const mainSync = (filePath, data, options) => {
8176
return writeFileAtomic.sync(filePath, `${json}${trailingNewline}`, {mode: options.mode, chown: false});
8277
};
8378

84-
module.exports = async (filePath, data, options) => {
85-
await makeDir(path.dirname(filePath), {fs});
86-
return init(main, filePath, data, options);
87-
};
79+
export async function writeJsonFile(filePath, data, options) {
80+
await fsPromises.mkdir(path.dirname(filePath), {recursive: true});
81+
await init(main, filePath, data, options);
82+
}
8883

89-
module.exports.sync = (filePath, data, options) => {
90-
makeDir.sync(path.dirname(filePath), {fs});
84+
export function writeJsonFileSync(filePath, data, options) {
85+
fs.mkdirSync(path.dirname(filePath), {recursive: true});
9186
init(mainSync, filePath, data, options);
92-
};
87+
}

index.test-d.ts

+27-28
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,20 @@
1-
import {expectType} from 'tsd';
2-
import writeJsonFile = require('.');
3-
import {sync, Replacer, SortKeys} from '.';
1+
import {expectType, expectAssignable} from 'tsd';
2+
import {writeJsonFile, writeJsonFileSync, Replacer, SortKeys} from './index.js';
43

5-
expectType<SortKeys>(() => 1);
6-
expectType<SortKeys>((a: string) => a.length);
7-
expectType<SortKeys>((a: string, b: string) => a.length - b.length);
4+
expectAssignable<SortKeys>(() => 1);
5+
expectAssignable<SortKeys>((a: string) => a.length);
6+
expectAssignable<SortKeys>((a: string, b: string) => a.length - b.length);
87

9-
expectType<Replacer>(() => 1);
10-
expectType<Replacer>(() => 'unicorn');
11-
expectType<Replacer>(() => true);
12-
expectType<Replacer>(() => null);
13-
expectType<Replacer>(() => undefined);
14-
expectType<Replacer>(() => ({unicorn: '🦄'}));
15-
expectType<Replacer>(() => ['unicorn', 1]);
16-
expectType<Replacer>(() => () => 'foo');
17-
expectType<Replacer>((key: string) => key.toUpperCase());
18-
expectType<Replacer>((key: string, value: string) => (key + value).toUpperCase());
8+
expectAssignable<Replacer>(() => 1);
9+
expectAssignable<Replacer>(() => 'unicorn');
10+
expectAssignable<Replacer>(() => true);
11+
expectAssignable<Replacer>(() => null);
12+
expectAssignable<Replacer>(() => undefined);
13+
expectAssignable<Replacer>(() => ({unicorn: '🦄'}));
14+
expectAssignable<Replacer>(() => ['unicorn', 1]);
15+
expectAssignable<Replacer>(() => () => 'foo');
16+
expectAssignable<Replacer>((key: string) => key.toUpperCase());
17+
expectAssignable<Replacer>((key: string, value: unknown) => (key + (value as string)).toUpperCase());
1918

2019
expectType<Promise<void>>(writeJsonFile('unicorn.json', {unicorn: '🦄'}));
2120
expectType<Promise<void>>(writeJsonFile('unicorn.json', '🦄'));
@@ -30,15 +29,15 @@ expectType<Promise<void>>(writeJsonFile('unicorn.json', {unicorn: '🦄'}, {sort
3029
expectType<Promise<void>>(writeJsonFile('unicorn.json', {unicorn: '🦄'}, {sortKeys: (a: string, b: string) => a.length - b.length}));
3130
expectType<Promise<void>>(writeJsonFile('unicorn.json', {unicorn: '🦄'}, {sortKeys: true}));
3231

33-
expectType<void>(sync('unicorn.json', {unicorn: '🦄'}));
34-
expectType<void>(sync('unicorn.json', '🦄'));
35-
expectType<void>(sync('date.json', new Date()));
36-
expectType<void>(sync('unicorn.json', {unicorn: '🦄'}, {detectIndent: true}));
37-
expectType<void>(sync('unicorn.json', {unicorn: '🦄'}, {indent: ' '}));
38-
expectType<void>(sync('unicorn.json', {unicorn: '🦄'}, {indent: 4}));
39-
expectType<void>(sync('unicorn.json', {unicorn: '🦄'}, {mode: 0o666}));
40-
expectType<void>(sync('unicorn.json', {unicorn: '🦄'}, {replacer: ['unicorn', 1]}));
41-
expectType<void>(sync('unicorn.json', {unicorn: '🦄'}, {replacer: () => 'unicorn'}));
42-
expectType<void>(sync('unicorn.json', {unicorn: '🦄'}, {sortKeys: () => -1}));
43-
expectType<void>(sync('unicorn.json', {unicorn: '🦄'}, {sortKeys: (a: string, b: string) => a.length - b.length}));
44-
expectType<void>(sync('unicorn.json', {unicorn: '🦄'}, {sortKeys: true}));
32+
expectType<void>(writeJsonFileSync('unicorn.json', {unicorn: '🦄'}));
33+
expectType<void>(writeJsonFileSync('unicorn.json', '🦄'));
34+
expectType<void>(writeJsonFileSync('date.json', new Date()));
35+
expectType<void>(writeJsonFileSync('unicorn.json', {unicorn: '🦄'}, {detectIndent: true}));
36+
expectType<void>(writeJsonFileSync('unicorn.json', {unicorn: '🦄'}, {indent: ' '}));
37+
expectType<void>(writeJsonFileSync('unicorn.json', {unicorn: '🦄'}, {indent: 4}));
38+
expectType<void>(writeJsonFileSync('unicorn.json', {unicorn: '🦄'}, {mode: 0o666}));
39+
expectType<void>(writeJsonFileSync('unicorn.json', {unicorn: '🦄'}, {replacer: ['unicorn', 1]}));
40+
expectType<void>(writeJsonFileSync('unicorn.json', {unicorn: '🦄'}, {replacer: () => 'unicorn'}));
41+
expectType<void>(writeJsonFileSync('unicorn.json', {unicorn: '🦄'}, {sortKeys: () => -1}));
42+
expectType<void>(writeJsonFileSync('unicorn.json', {unicorn: '🦄'}, {sortKeys: (a: string, b: string) => a.length - b.length}));
43+
expectType<void>(writeJsonFileSync('unicorn.json', {unicorn: '🦄'}, {sortKeys: true}));

license

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) Sindre Sorhus <[email protected]> (sindresorhus.com)
3+
Copyright (c) Sindre Sorhus <[email protected]> (https://sindresorhus.com)
44

55
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:
66

package.json

+12-12
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@
88
"author": {
99
"name": "Sindre Sorhus",
1010
"email": "[email protected]",
11-
"url": "sindresorhus.com"
11+
"url": "https://sindresorhus.com"
1212
},
13+
"type": "module",
14+
"exports": "./index.js",
1315
"engines": {
14-
"node": ">=8.3"
16+
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
1517
},
1618
"scripts": {
1719
"test": "xo && ava && tsd"
@@ -35,17 +37,15 @@
3537
"atomically"
3638
],
3739
"dependencies": {
38-
"detect-indent": "^6.0.0",
39-
"graceful-fs": "^4.1.15",
40-
"is-plain-obj": "^2.0.0",
41-
"make-dir": "^3.0.0",
42-
"sort-keys": "^4.0.0",
43-
"write-file-atomic": "^3.0.0"
40+
"detect-indent": "^7.0.0",
41+
"is-plain-obj": "^4.0.0",
42+
"sort-keys": "^5.0.0",
43+
"write-file-atomic": "^3.0.3"
4444
},
4545
"devDependencies": {
46-
"ava": "^1.4.1",
47-
"tempy": "^0.3.0",
48-
"tsd": "^0.8.0",
49-
"xo": "^0.25.3"
46+
"ava": "^3.15.0",
47+
"tempy": "^1.0.1",
48+
"tsd": "^0.17.0",
49+
"xo": "^0.44.0"
5050
}
5151
}

readme.md

+3-5
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,9 @@ $ npm install write-json-file
1313
## Usage
1414

1515
```js
16-
const writeJsonFile = require('write-json-file');
16+
import {writeJsonFile} from 'write-json-file';
1717

18-
(async () => {
19-
await writeJsonFile('foo.json', {foo: true});
20-
})();
18+
await writeJsonFile('foo.json', {foo: true});
2119
```
2220

2321
## API
@@ -68,7 +66,7 @@ Passed into [`JSON.stringify`](https://developer.mozilla.org/en-US/docs/Web/Java
6866
Type: `number`\
6967
Default: `0o666`
7068

71-
[Mode](https://en.wikipedia.org/wiki/File_system_permissions#Numeric_notation) used when writing the file.
69+
The [mode](https://en.wikipedia.org/wiki/File_system_permissions#Numeric_notation) used when writing the file.
7270

7371
## write-json-file for enterprise
7472

0 commit comments

Comments
 (0)