From 8981f214084326c55b053c76182acd741262c057 Mon Sep 17 00:00:00 2001 From: fengmk2 Date: Fri, 22 Sep 2023 20:56:46 +0800 Subject: [PATCH] feat: refactor with typescript to support cjs and esm both (#37) BREAKING CHANGE: Drop Node.js < 16 support - rename `interface()` to `getInterfaceAddress()` --- .eslintrc | 5 +- .github/workflows/codeql-analysis.yml | 70 ------ .github/workflows/nodejs.yml | 9 +- .github/workflows/release.yml | 6 +- .gitignore | 4 +- CHANGELOG.md | 77 ++++++ History.md | 74 ------ README.md | 112 +++++++-- example/hello.cjs | 15 ++ example/hello.mjs | 11 + lib/address.d.ts | 28 --- lib/address.js | 263 -------------------- package.json | 73 ++++-- src/address.ts | 277 ++++++++++++++++++++++ src/index.ts | 4 + src/promises.ts | 32 +++ test/{address.test.js => address.test.ts} | 144 ++++++----- test/fixtures/ts/test.ts | 16 +- test/fixtures/ts/tsconfig.json | 6 +- test/promises.test.ts | 22 ++ test/ts.test.js | 13 - test/ts.test.ts | 16 ++ tsconfig.json | 10 + 23 files changed, 720 insertions(+), 567 deletions(-) delete mode 100644 .github/workflows/codeql-analysis.yml delete mode 100644 History.md create mode 100644 example/hello.cjs create mode 100644 example/hello.mjs delete mode 100644 lib/address.d.ts delete mode 100644 lib/address.js create mode 100644 src/address.ts create mode 100644 src/index.ts create mode 100644 src/promises.ts rename test/{address.test.js => address.test.ts} (53%) create mode 100644 test/promises.test.ts delete mode 100644 test/ts.test.js create mode 100644 test/ts.test.ts create mode 100644 tsconfig.json diff --git a/.eslintrc b/.eslintrc index c799fe5..9bcdb46 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,3 +1,6 @@ { - "extends": "eslint-config-egg" + "extends": [ + "eslint-config-egg/typescript", + "eslint-config-egg/lib/rules/enforce-node-prefix" + ] } diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml deleted file mode 100644 index 3b6a3c2..0000000 --- a/.github/workflows/codeql-analysis.yml +++ /dev/null @@ -1,70 +0,0 @@ -# For most projects, this workflow file will not need changing; you simply need -# to commit it to your repository. -# -# You may wish to alter this file to override the set of languages analyzed, -# or to provide custom queries or build logic. -# -# ******** NOTE ******** -# We have attempted to detect the languages in your repository. Please check -# the `language` matrix defined below to confirm you have the correct set of -# supported CodeQL languages. -# -name: "CodeQL" - -on: - push: - branches: [ master ] - pull_request: - # The branches below must be a subset of the branches above - branches: [ master ] - schedule: - - cron: '17 10 * * 2' - -jobs: - analyze: - name: Analyze - runs-on: ubuntu-latest - permissions: - actions: read - contents: read - security-events: write - - strategy: - fail-fast: false - matrix: - language: [ 'javascript' ] - # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] - # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support - - steps: - - name: Checkout repository - uses: actions/checkout@v3 - - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v2 - with: - languages: ${{ matrix.language }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - # queries: ./path/to/local/query, your-org/your-repo/queries@main - - # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild - uses: github/codeql-action/autobuild@v2 - - # โ„น๏ธ Command-line programs to run using the OS shell. - # ๐Ÿ“š See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun - - # โœ๏ธ If the Autobuild fails above, remove it and uncomment the following three lines - # and modify them (or add more) to build your code if your project - # uses a compiled language - - #- run: | - # make bootstrap - # make release - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index c7a5144..e807d60 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -7,15 +7,10 @@ on: pull_request: branches: [ master ] - schedule: - - cron: '0 2 * * *' - - workflow_dispatch: {} - jobs: Job: name: Node.js - uses: artusjs/github-actions/.github/workflows/node-test.yml@v1 + uses: node-modules/github-actions/.github/workflows/node-test.yml@master with: os: 'ubuntu-latest, macos-latest' - version: '14, 16, 18' + version: '16, 18, 20' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c6cc6c8..a4e1158 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,17 +1,13 @@ name: Release on: - # ๅˆๅนถๅŽ่‡ชๅŠจๅ‘ๅธƒ push: branches: [ master ] - # ๆ‰‹ๅŠจๅ‘ๅธƒ - workflow_dispatch: {} - jobs: release: name: Node.js - uses: artusjs/github-actions/.github/workflows/node-release.yml@v1 + uses: node-modules/github-actions/.github/workflows/node-release.yml@master secrets: NPM_TOKEN: ${{ secrets.NPM_TOKEN }} GIT_TOKEN: ${{ secrets.GIT_TOKEN }} diff --git a/.gitignore b/.gitignore index 2d788b2..b4b3d69 100644 --- a/.gitignore +++ b/.gitignore @@ -16,4 +16,6 @@ npm-debug.log .DS_Store .idea/ -test/fixtures/ts/*.js \ No newline at end of file +test/fixtures/ts/*.js +.tshy* +dist/ diff --git a/CHANGELOG.md b/CHANGELOG.md index 114d66c..2e94234 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,3 +6,80 @@ ### Bug Fixes * Auto release on action ([#33](https://github.com/node-modules/address/issues/33)) ([36b30d3](https://github.com/node-modules/address/commit/36b30d3708bd5fb09dd2e9a9d4741dd9112eb890)) + +--- + + +1.2.1 / 2022-09-13 +================== + +**fixes** + * [[`c316a04`](http://github.com/node-modules/address/commit/c316a044aedeadf438c2c2a7278d51f0861df8af)] - fix: local addresses should be ignored on interface (#32) (Jon Kelley <>) + +**others** + * [[`823b70c`](http://github.com/node-modules/address/commit/823b70c2f53ab96d6e25041aa444436d906c59ef)] - ๐Ÿค– TEST: Run test on GitHub action (#27) (fengmk2 <>) + * [[`2b5fb44`](http://github.com/node-modules/address/commit/2b5fb44ca1ff1a0d64768e8d42845ec377b9e3f8)] - Create codeql-analysis.yml (fengmk2 <>) + +1.2.0 / 2022-04-29 +================== + +**features** + * [[`fe81a41`](http://github.com/node-modules/address/commit/fe81a415403ba46d7bc09d76a2f9fc46bc2fc803)] - feat: address.ip() supports node 18 (#26) (Yuheng Zhang <>) + +1.1.2 / 2019-08-26 +================== + +**fixes** + * [[`304754e`](http://github.com/node-modules/address/commit/304754ea4ef0dd34db7ba34745f4f4543afc064c)] - fix: fix declarations (#20) (ๅ–็Œฉ <>) + +1.1.1 / 2019-08-22 +================== + +**fixes** + * [[`19884ff`](http://github.com/node-modules/address/commit/19884ffbe9ad75f9a66889a031db4b806da1f822)] - fix: update d.ts (#18) (MarioDu <>) + +1.1.0 / 2019-04-24 +================== + +**features** + * [[`7544592`](http://github.com/node-modules/address/commit/75445923a6f737fc21e3cf592f749bf014b7b4ce)] - feat: Add typings (#15) (Mathieu TUDISCO <>) + +1.0.3 / 2017-08-24 +================== + +**fixes** + * [[`ed491c5`](http://github.com/node-modules/address/commit/ed491c5bd353118e4e4d384f47f13c3e1cfeb80e)] - fix: ignore wrong mac address on node 8.x (#10) (fengmk2 <>) + +1.0.2 / 2017-05-26 +================== + + * fix: win32 get mac failed (#9) + +1.0.1 / 2016-09-30 +================== + + * test: remove 0.12 + * fix: search interface before family match + * add contributors + +1.0.0 / 2015-08-06 +================== + + * chore: use npm scripts instead of Makefile + * add benchmark + +0.0.3 / 2013-11-04 +================== + + * get the first not local ip when interface not exists + +0.0.2 / 2013-08-08 +================== + + * use networkInterface() to get mac fix #3 + +0.0.1 / 2013-07-31 +================== + + * ip(), ipv6(), mac(), dns() work on osx and linux now. + * first commit diff --git a/History.md b/History.md deleted file mode 100644 index 1cf29af..0000000 --- a/History.md +++ /dev/null @@ -1,74 +0,0 @@ - -1.2.1 / 2022-09-13 -================== - -**fixes** - * [[`c316a04`](http://github.com/node-modules/address/commit/c316a044aedeadf438c2c2a7278d51f0861df8af)] - fix: local addresses should be ignored on interface (#32) (Jon Kelley <>) - -**others** - * [[`823b70c`](http://github.com/node-modules/address/commit/823b70c2f53ab96d6e25041aa444436d906c59ef)] - ๐Ÿค– TEST: Run test on GitHub action (#27) (fengmk2 <>) - * [[`2b5fb44`](http://github.com/node-modules/address/commit/2b5fb44ca1ff1a0d64768e8d42845ec377b9e3f8)] - Create codeql-analysis.yml (fengmk2 <>) - -1.2.0 / 2022-04-29 -================== - -**features** - * [[`fe81a41`](http://github.com/node-modules/address/commit/fe81a415403ba46d7bc09d76a2f9fc46bc2fc803)] - feat: address.ip() supports node 18 (#26) (Yuheng Zhang <>) - -1.1.2 / 2019-08-26 -================== - -**fixes** - * [[`304754e`](http://github.com/node-modules/address/commit/304754ea4ef0dd34db7ba34745f4f4543afc064c)] - fix: fix declarations (#20) (ๅ–็Œฉ <>) - -1.1.1 / 2019-08-22 -================== - -**fixes** - * [[`19884ff`](http://github.com/node-modules/address/commit/19884ffbe9ad75f9a66889a031db4b806da1f822)] - fix: update d.ts (#18) (MarioDu <>) - -1.1.0 / 2019-04-24 -================== - -**features** - * [[`7544592`](http://github.com/node-modules/address/commit/75445923a6f737fc21e3cf592f749bf014b7b4ce)] - feat: Add typings (#15) (Mathieu TUDISCO <>) - -1.0.3 / 2017-08-24 -================== - -**fixes** - * [[`ed491c5`](http://github.com/node-modules/address/commit/ed491c5bd353118e4e4d384f47f13c3e1cfeb80e)] - fix: ignore wrong mac address on node 8.x (#10) (fengmk2 <>) - -1.0.2 / 2017-05-26 -================== - - * fix: win32 get mac failed (#9) - -1.0.1 / 2016-09-30 -================== - - * test: remove 0.12 - * fix: search interface before family match - * add contributors - -1.0.0 / 2015-08-06 -================== - - * chore: use npm scripts instead of Makefile - * add benchmark - -0.0.3 / 2013-11-04 -================== - - * get the first not local ip when interface not exists - -0.0.2 / 2013-08-08 -================== - - * use networkInterface() to get mac fix #3 - -0.0.1 / 2013-07-31 -================== - - * ip(), ipv6(), mac(), dns() work on osx and linux now. - * first commit diff --git a/README.md b/README.md index f108b82..fc7b745 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,4 @@ -address -======= +# address [![NPM version][npm-image]][npm-url] [![Node.js CI](https://github.com/node-modules/address/actions/workflows/nodejs.yml/badge.svg)](https://github.com/node-modules/address/actions/workflows/nodejs.yml) @@ -13,42 +12,85 @@ address [download-image]: https://img.shields.io/npm/dm/address.svg?style=flat-square [download-url]: https://npmjs.org/package/address -Get current machine IP, MAC and DNS servers. +Get current machine IPv4, IPv6, MAC and DNS servers. DNS servers receive from `/etc/resolv.conf`. ## Install ```bash -$ npm install address +npm install address ``` ## Usage Get IP is sync and get MAC is async for now. +- esm & typescript + +```ts +import { ip, ipv6, mac } from 'address'; + +// default interface 'eth' on linux, 'en' on osx. +ip(); // '192.168.0.2' +ipv6(); // 'fe80::7aca:39ff:feb0:e67d' +mac(function (err, addr) { + console.log(addr); // '78:ca:39:b0:e6:7d' +}); + +// local loopback +ip('lo'); // '127.0.0.1' + +// vboxnet MAC +mac('vboxnet', function (err, addr) { + console.log(addr); // '0a:00:27:00:00:00' +}); +``` + +- commonjs + ```js -const address = require('address'); +const { ip, ipv6, mac } = require('address'); // default interface 'eth' on linux, 'en' on osx. -address.ip(); // '192.168.0.2' -address.ipv6(); // 'fe80::7aca:39ff:feb0:e67d' -address.mac(function (err, addr) { +ip(); // '192.168.0.2' +ipv6(); // 'fe80::7aca:39ff:feb0:e67d' +mac(function (err, addr) { console.log(addr); // '78:ca:39:b0:e6:7d' }); // local loopback -address.ip('lo'); // '127.0.0.1' +ip('lo'); // '127.0.0.1' // vboxnet MAC -address.mac('vboxnet', function (err, addr) { +mac('vboxnet', function (err, addr) { console.log(addr); // '0a:00:27:00:00:00' }); ``` ### Get all addresses: IPv4, IPv6 and MAC +- esm & typescript + +```ts +import { address } from 'address'; + +address((err, addrs) => { + console.log(addrs.ip, addrs.ipv6, addrs.mac); + // '192.168.0.2', 'fe80::7aca:39ff:feb0:e67d', '78:ca:39:b0:e6:7d' +}); + +address('vboxnet', (err, addrs) => { + console.log(addrs.ip, addrs.ipv6, addrs.mac); + // '192.168.56.1', null, '0a:00:27:00:00:00' +}); +``` + +- commonjs + ```js +const { address } = require('address'); + address((err, addrs) => { console.log(addrs.ip, addrs.ipv6, addrs.mac); // '192.168.0.2', 'fe80::7aca:39ff:feb0:e67d', '78:ca:39:b0:e6:7d' @@ -62,20 +104,58 @@ address('vboxnet', (err, addrs) => { ### Get an interface info with family +- esm & typescript + +```ts +import { getInterfaceAddress } from 'address'; + +getInterfaceAddress('IPv4', 'eth1'); +// { address: '192.168.1.1', family: 'IPv4', mac: '78:ca:39:b0:e6:7d' } +``` + +- commonjs + ```js -address.interface('IPv4', 'eth1'); +const { getInterfaceAddress } = require('address'); + +getInterfaceAddress('IPv4', 'eth1'); // { address: '192.168.1.1', family: 'IPv4', mac: '78:ca:39:b0:e6:7d' } ``` ### Get DNS servers +- esm & typescript + ```js -address.dns((err, addrs) => { - console.log(addrs); +import { dns } from 'address'; + +dns((err, servers) => { + console.log(servers); + // ['10.13.2.1', '10.13.2.6'] +}); +``` + +- commonjs + +```js +const { dns } = require('address'); + +dns((err, servers) => { + console.log(servers); // ['10.13.2.1', '10.13.2.6'] }); ``` +### Promise style apis + +```ts +import { address, mac, dns } from 'address/promises'; + +const addr = await address(); +const macAddress = await mac(); +const servers = await dns(); +``` + ## License [MIT](LICENSE.txt) @@ -84,10 +164,10 @@ address.dns((err, addrs) => { ## Contributors -|[
fengmk2](https://github.com/fengmk2)
|[
alsotang](https://github.com/alsotang)
|[
jkelleyrtp](https://github.com/jkelleyrtp)
|[
mariodu](https://github.com/mariodu)
|[
mathieutu](https://github.com/mathieutu)
|[
zhangyuheng](https://github.com/zhangyuheng)
| +|[
fengmk2](https://github.com/fengmk2)
|[
alsotang](https://github.com/alsotang)
|[
jkelleyrtp](https://github.com/jkelleyrtp)
|[
slyon](https://github.com/slyon)
|[
mariodu](https://github.com/mariodu)
|[
mathieutu](https://github.com/mathieutu)
| | :---: | :---: | :---: | :---: | :---: | :---: | -[
coolme200](https://github.com/coolme200)
|[
whxaxes](https://github.com/whxaxes)
+[
zhangyuheng](https://github.com/zhangyuheng)
|[
semantic-release-bot](https://github.com/semantic-release-bot)
|[
coolme200](https://github.com/coolme200)
|[
whxaxes](https://github.com/whxaxes)
-This project follows the git-contributor [spec](https://github.com/xudafeng/git-contributor), auto updated at `Tue Sep 13 2022 09:09:11 GMT+0800`. +This project follows the git-contributor [spec](https://github.com/xudafeng/git-contributor), auto updated at `Fri Sep 22 2023 20:49:32 GMT+0800`. diff --git a/example/hello.cjs b/example/hello.cjs new file mode 100644 index 0000000..a470d95 --- /dev/null +++ b/example/hello.cjs @@ -0,0 +1,15 @@ +const address = require('address').default; +const { ip, ipv6 } = require('address'); +const { address: addr } = require('address/promises'); + +async function main() { + console.log('ip=%o', ip()); + console.log('ipv6=%o', ipv6()); + console.log('await address=%o', await addr()); + + address((_, a) => { + console.log('callback address=%o', a); + }); +} + +main(); diff --git a/example/hello.mjs b/example/hello.mjs new file mode 100644 index 0000000..2f4d8f3 --- /dev/null +++ b/example/hello.mjs @@ -0,0 +1,11 @@ +import address from 'address'; +import { ip, ipv6 } from 'address'; +import { address as addr } from 'address/promises'; + +console.log('ip=%o', ip()); +console.log('ipv6=%o', ipv6()); +console.log('await address=%o', await addr()); + +address((_, a) => { + console.log('callback address=%o', a); +}); diff --git a/lib/address.d.ts b/lib/address.d.ts deleted file mode 100644 index be66ed0..0000000 --- a/lib/address.d.ts +++ /dev/null @@ -1,28 +0,0 @@ -export = address; - -declare interface Address { - ip: string; - ipv6: string; - mac: string; -} - -declare type AddressCallback = (err: Error, addr: Address) => void; -declare type MacCallback = (err: Error, addr: string) => void; -declare type DnsCallback = (err: Error, servers: string[]) => void; - -declare function address(interfaceName: string, callback: AddressCallback): void; -declare function address(callback: AddressCallback): void; - -declare namespace address { - const MAC_IP_RE: RegExp; - const MAC_RE: RegExp; - - function dns(filepath: string, callback: DnsCallback): void; - function dns(callback: DnsCallback): void; - - function ip(interfaceName?: string): any; - function ipv6(interfaceName?: string): any; - - function mac(interfaceName: string, callback: MacCallback): void; - function mac(callback: MacCallback): void; -} diff --git a/lib/address.js b/lib/address.js deleted file mode 100644 index d4e5ebc..0000000 --- a/lib/address.js +++ /dev/null @@ -1,263 +0,0 @@ -'use strict'; - -var os = require('os'); -var fs = require('fs'); -var child = require('child_process'); - -var DEFAULT_RESOLV_FILE = '/etc/resolv.conf'; - -function getInterfaceName() { - var val = 'eth'; - var platform = os.platform(); - if (platform === 'darwin') { - val = 'en'; - } else if (platform === 'win32') { - val = null; - } - return val; -} - -function getIfconfigCMD() { - if (os.platform() === 'win32') { - return 'ipconfig/all'; - } - return '/sbin/ifconfig'; -} - -// typeof os.networkInterfaces family is a number (v18.0.0) -// types: 'IPv4' | 'IPv6' => 4 | 6 -// @see https://github.com/nodejs/node/issues/42861 -function matchName(actualFamily, expectedFamily) { - if (expectedFamily === 'IPv4') { - return actualFamily === 'IPv4' || actualFamily === 4; - } - if (expectedFamily === 'IPv6') { - return actualFamily === 'IPv6' || actualFamily === 6; - } - return actualFamily === expectedFamily; -} - -/** - * Get all addresses. - * - * @param {String} [interfaceName] interface name, default is 'eth' on linux, 'en' on mac os. - * @param {Function(err, addr)} callback - * - {Object} addr { - * - {String} ip - * - {String} ipv6 - * - {String} mac - * } - */ -function address(interfaceName, callback) { - if (typeof interfaceName === 'function') { - callback = interfaceName; - interfaceName = null; - } - - var addr = { - ip: address.ip(interfaceName), - ipv6: address.ipv6(interfaceName), - mac: null - }; - address.mac(interfaceName, function (err, mac) { - if (mac) { - addr.mac = mac; - } - callback(err, addr); - }); -} - -address.interface = function (family, name) { - var interfaces = os.networkInterfaces(); - var noName = !name; - name = name || getInterfaceName(); - family = family || 'IPv4'; - for (var i = -1; i < 8; i++) { - var interfaceName = name + (i >= 0 ? i : ''); // support 'lo' and 'lo0' - var items = interfaces[interfaceName]; - if (items) { - for (var j = 0; j < items.length; j++) { - var item = items[j]; - if (matchName(item.family, family)) { - return item; - } - } - } - } - - if (noName) { - // filter all loopback or local addresses - for (var k in interfaces) { - var items = interfaces[k]; - for (var i = 0; i < items.length; i++) { - var item = items[i]; - // all 127 addresses are local and should be ignored - if (matchName(item.family, family) && !item.address.startsWith('127.')) { - return item; - } - } - } - } - return; -}; - -/** - * Get current machine IPv4 - * - * @param {String} [interfaceName] interface name, default is 'eth' on linux, 'en' on mac os. - * @return {String} IP address - */ -address.ip = function (interfaceName) { - var item = address.interface('IPv4', interfaceName); - return item && item.address; -}; - -/** - * Get current machine IPv6 - * - * @param {String} [interfaceName] interface name, default is 'eth' on linux, 'en' on mac os. - * @return {String} IP address - */ -address.ipv6 = function (interfaceName) { - var item = address.interface('IPv6', interfaceName); - return item && item.address; -}; - -// osx start line 'en0: flags=8863 mtu 1500' -// linux start line 'eth0 Link encap:Ethernet HWaddr 00:16:3E:00:0A:29 ' -var MAC_OSX_START_LINE = /^(\w+)\:\s+flags=/; -var MAC_LINUX_START_LINE = /^(\w+)\s{2,}link encap:\w+/i; - -// ether 78:ca:39:b0:e6:7d -// HWaddr 00:16:3E:00:0A:29 -var MAC_RE = address.MAC_RE = /(?:ether|HWaddr)\s+((?:[a-z0-9]{2}\:){5}[a-z0-9]{2})/i; - -// osx: inet 192.168.2.104 netmask 0xffffff00 broadcast 192.168.2.255 -// linux: inet addr:10.125.5.202 Bcast:10.125.15.255 Mask:255.255.240.0 -var MAC_IP_RE = address.MAC_IP_RE = /inet\s(?:addr\:)?(\d+\.\d+\.\d+\.\d+)/; - -function getMAC(content, interfaceName, matchIP) { - var lines = content.split('\n'); - for (var i = 0; i < lines.length; i++) { - var line = lines[i].trimRight(); - var m = MAC_OSX_START_LINE.exec(line) || MAC_LINUX_START_LINE.exec(line); - if (!m) { - continue; - } - - // check interface name - var name = m[1]; - if (name.indexOf(interfaceName) !== 0) { - continue; - } - - var ip = null; - var mac = null; - var match = MAC_RE.exec(line); - if (match) { - mac = match[1]; - } - - i++; - while (true) { - line = lines[i]; - if (!line || MAC_OSX_START_LINE.exec(line) || MAC_LINUX_START_LINE.exec(line)) { - i--; - break; // hit next interface, handle next interface - } - if (!mac) { - match = MAC_RE.exec(line); - if (match) { - mac = match[1]; - } - } - - if (!ip) { - match = MAC_IP_RE.exec(line); - if (match) { - ip = match[1]; - } - } - - i++; - } - - if (ip === matchIP) { - return mac; - } - } -} - -/** - * Get current machine MAC address - * - * @param {String} [interfaceName] interface name, default is 'eth' on linux, 'en' on mac os. - * @param {Function(err, address)} callback - */ -address.mac = function (interfaceName, callback) { - if (typeof interfaceName === 'function') { - callback = interfaceName; - interfaceName = null; - } - interfaceName = interfaceName || getInterfaceName(); - var item = address.interface('IPv4', interfaceName); - if (!item) { - return callback(); - } - - // https://github.com/nodejs/node/issues/13581 - // bug in node 7.x and <= 8.4.0 - if (!process.env.CI && (item.mac === 'ff:00:00:00:00:00' || item.mac === '00:00:00:00:00:00')) { - // wrong address, ignore it - item.mac = ''; - } - - if (item.mac) { - return callback(null, item.mac); - } - - child.exec(getIfconfigCMD(), {timeout: 5000}, function (err, stdout, stderr) { - if (err || !stdout) { - return callback(err); - } - - var mac = getMAC(stdout || '', interfaceName, item.address); - callback(null, mac); - }); -}; - -// nameserver 172.24.102.254 -var DNS_SERVER_RE = /^nameserver\s+(\d+\.\d+\.\d+\.\d+)$/i; - -/** - * Get DNS servers. - * - * @param {String} [filepath] resolv config file path. default is '/etc/resolv.conf'. - * @param {Function(err, servers)} callback - */ -address.dns = function (filepath, callback) { - if (typeof filepath === 'function') { - callback = filepath; - filepath = null; - } - filepath = filepath || DEFAULT_RESOLV_FILE; - fs.readFile(filepath, 'utf8', function (err, content) { - if (err) { - return callback(err); - } - var servers = []; - content = content || ''; - var lines = content.split('\n'); - for (var i = 0; i < lines.length; i++) { - var line = lines[i].trim(); - var m = DNS_SERVER_RE.exec(line); - if (m) { - servers.push(m[1]); - } - } - - callback(null, servers); - }); -}; - -module.exports = address; diff --git a/package.json b/package.json index 1d9b814..5472bd4 100644 --- a/package.json +++ b/package.json @@ -2,27 +2,28 @@ "name": "address", "version": "1.2.2", "description": "Get current machine IP, MAC and DNS servers.", - "main": "lib/address.js", - "types": "lib/address.d.ts", - "files": [ - "lib" - ], "scripts": { - "lint": "eslint test", + "lint": "eslint src test --ext .ts", + "pretest": "npm run lint -- --fix && npm run prepublishOnly", "test": "egg-bin test", + "preci": "npm run prepublishOnly", "ci": "egg-bin cov", - "contributors": "git-contributor" + "contributor": "git-contributor", + "prepublishOnly": "tshy && tshy-after" }, - "dependencies": {}, "devDependencies": { - "@types/node": "14", - "egg-bin": "^5.6.1", - "eslint": "^8.30.0", - "eslint-config-egg": "^12.1.0", - "git-contributor": "^1.1.0", - "mm": "*", - "runscript": "^1.4.0", - "typescript": "4" + "@eggjs/tsconfig": "^1.3.3", + "@types/mocha": "^10.0.1", + "@types/node": "^20.6.3", + "egg-bin": "^6.5.2", + "eslint": "^8.49.0", + "eslint-config-egg": "^13.0.0", + "git-contributor": "^2.1.5", + "mm": "^3.3.0", + "runscript": "^1.5.3", + "tshy": "^1.1.1", + "tshy-after": "^1.0.0", + "typescript": "^5.2.2" }, "repository": { "type": "git", @@ -35,8 +36,44 @@ "mac" ], "engines": { - "node": ">= 10.0.0" + "node": ">= 16.0.0" }, "author": "fengmk2 ", - "license": "MIT" + "license": "MIT", + "files": [ + "dist", + "src" + ], + "type": "module", + "tshy": { + "exports": { + "./package.json": "./package.json", + "./promises": "./src/promises.ts", + ".": "./src/index.ts" + } + }, + "exports": { + "./package.json": "./package.json", + "./promises": { + "import": { + "types": "./dist/esm/promises.d.ts", + "default": "./dist/esm/promises.js" + }, + "require": { + "types": "./dist/commonjs/promises.d.ts", + "default": "./dist/commonjs/promises.js" + } + }, + ".": { + "import": { + "types": "./dist/esm/index.d.ts", + "default": "./dist/esm/index.js" + }, + "require": { + "types": "./dist/commonjs/index.d.ts", + "default": "./dist/commonjs/index.js" + } + } + }, + "types": "./dist/commonjs/index.d.ts" } diff --git a/src/address.ts b/src/address.ts new file mode 100644 index 0000000..883a017 --- /dev/null +++ b/src/address.ts @@ -0,0 +1,277 @@ +import os from 'node:os'; +import fs from 'node:fs/promises'; +import childProcess from 'node:child_process'; + +const DEFAULT_RESOLV_FILE = '/etc/resolv.conf'; + +// osx start line 'en0: flags=8863 mtu 1500' +// linux start line 'eth0 Link encap:Ethernet HWaddr 00:16:3E:00:0A:29 ' +const MAC_OSX_START_LINE = /^(\w+)\:\s+flags=/; +const MAC_LINUX_START_LINE = /^(\w+)\s{2,}link encap:\w+/i; + +// ether 78:ca:39:b0:e6:7d +// HWaddr 00:16:3E:00:0A:29 +export const MAC_RE = /(?:ether|HWaddr)\s+((?:[a-z0-9]{2}\:){5}[a-z0-9]{2})/i; + +// osx: inet 192.168.2.104 netmask 0xffffff00 broadcast 192.168.2.255 +// linux: inet addr:10.125.5.202 Bcast:10.125.15.255 Mask:255.255.240.0 +export const MAC_IP_RE = /inet\s(?:addr\:)?(\d+\.\d+\.\d+\.\d+)/; + +export interface Address { + ip?: string; + ipv6?: string; + mac?: string; +} + +export type AddressCallback = (err: Error | null, addr: Address) => void; +export type MacCallback = (err?: Error | null, addr?: string | null) => void; +export type DnsCallback = (err?: Error | null, servers?: string[]) => void; + +function getDefaultInterfaceName() { + let val: string | undefined = 'eth'; + const platform = os.platform(); + if (platform === 'darwin') { + val = 'en'; + } else if (platform === 'win32') { + val = undefined; + } + return val; +} + +function getIfconfigCMD() { + if (os.platform() === 'win32') { + return 'ipconfig/all'; + } + return '/sbin/ifconfig'; +} + +// typeof os.networkInterfaces family is a number (v18.0.0) +// types: 'IPv4' | 'IPv6' => 4 | 6 +// @see https://github.com/nodejs/node/issues/42861 +function matchName(actualFamily: string | number, expectedFamily: string | number) { + if (expectedFamily === 'IPv4') { + return actualFamily === 'IPv4' || actualFamily === 4; + } + if (expectedFamily === 'IPv6') { + return actualFamily === 'IPv6' || actualFamily === 6; + } + return actualFamily === expectedFamily; +} + +export function getInterfaceAddress(family?: string, name?: string) { + const interfaces = os.networkInterfaces(); + const noName = !name; + name = name || getDefaultInterfaceName(); + family = family || 'IPv4'; + if (name) { + for (let i = -1; i < 8; i++) { + const interfaceName = name + (i >= 0 ? i : ''); // support 'lo' and 'lo0' + const items = interfaces[interfaceName]; + if (items) { + for (const item of items) { + if (matchName(item.family, family)) { + return item; + } + } + } + } + } + + if (noName) { + // filter all loopback or local addresses + for (const k in interfaces) { + const items = interfaces[k]; + if (items) { + for (const item of items) { + // all 127 addresses are local and should be ignored + if (matchName(item.family, family) && !item.address.startsWith('127.')) { + return item; + } + } + } + } + } + return; +} + +/** + * Get current machine IPv4 + * + * interfaceName: interface name, default is 'eth' on linux, 'en' on mac os. + */ +export function ip(interfaceName?: string) { + const item = getInterfaceAddress('IPv4', interfaceName); + return item?.address; +} + +/** + * Get current machine IPv6 + * + * interfaceName: interface name, default is 'eth' on linux, 'en' on mac os. + */ +export function ipv6(interfaceName?: string) { + const item = getInterfaceAddress('IPv6', interfaceName); + return item?.address; +} + +function getMAC(content: string, interfaceName: string, matchIP: string) { + const lines = content.split('\n'); + for (let i = 0; i < lines.length; i++) { + let line = lines[i].trimEnd(); + const m = MAC_OSX_START_LINE.exec(line) || MAC_LINUX_START_LINE.exec(line); + if (!m) { + continue; + } + + // check interface name + const name = m[1]; + if (name.indexOf(interfaceName) !== 0) { + continue; + } + + let ip: string | null = null; + let mac: string | null = null; + let match = MAC_RE.exec(line); + if (match) { + mac = match[1]; + } + + i++; + // eslint-disable-next-line no-constant-condition + while (true) { + line = lines[i]; + if (!line || MAC_OSX_START_LINE.exec(line) || MAC_LINUX_START_LINE.exec(line)) { + i--; + break; // hit next interface, handle next interface + } + if (!mac) { + match = MAC_RE.exec(line); + if (match) { + mac = match[1]; + } + } + + if (!ip) { + match = MAC_IP_RE.exec(line); + if (match) { + ip = match[1]; + } + } + + i++; + } + + if (ip === matchIP) { + return mac; + } + } + return null; +} + +/** + * Get current machine MAC address + * + * interfaceName: name, default is 'eth' on linux, 'en' on mac os. + */ +export function mac(callback: MacCallback): void; +export function mac(interfaceName: string, callback: MacCallback): void; +export function mac(interfaceNameOrCallback: string | MacCallback, callback?: MacCallback) { + let interfaceName: string | undefined; + if (typeof interfaceNameOrCallback === 'function') { + callback = interfaceNameOrCallback; + } else { + interfaceName = interfaceNameOrCallback; + } + interfaceName = interfaceName || getDefaultInterfaceName(); + const item = getInterfaceAddress('IPv4', interfaceName); + if (!item) { + return callback!(); + } + + // https://github.com/nodejs/node/issues/13581 + // bug in node 7.x and <= 8.4.0 + if (!process.env.CI && (item.mac === 'ff:00:00:00:00:00' || item.mac === '00:00:00:00:00:00')) { + // wrong address, ignore it + item.mac = ''; + } + + if (item.mac) { + return callback!(null, item.mac); + } + + childProcess.exec(getIfconfigCMD(), { timeout: 5000 }, (err, stdout) => { + if (err || !stdout) { + return callback!(err); + } + + if (!interfaceName) { + return callback!(); + } + const mac = getMAC(stdout || '', interfaceName, item.address); + callback!(null, mac); + }); +} + +// nameserver 172.24.102.254 +const DNS_SERVER_RE = /^nameserver\s+(\d+\.\d+\.\d+\.\d+)$/i; + +/** + * Get DNS servers. + * + * filepath: resolv config file path. default is '/etc/resolv.conf'. + */ +export function dns(callback: DnsCallback): void; +export function dns(filepath: string, callback: DnsCallback): void; +export function dns(filepathOrCallback: string | DnsCallback, callback?: DnsCallback) { + let filepath: string | undefined; + if (typeof filepathOrCallback === 'function') { + callback = filepathOrCallback; + } else { + filepath = filepathOrCallback; + } + filepath = filepath || DEFAULT_RESOLV_FILE; + fs.readFile(filepath, 'utf8') + .then(content => { + const servers: string[] = []; + content = content || ''; + const lines = content.split('\n'); + for (const line of lines) { + const m = DNS_SERVER_RE.exec(line.trim()); + if (m) { + servers.push(m[1]); + } + } + callback!(null, servers); + }) + .catch(err => { + callback!(err); + }); +} + +/** + * Get all addresses. + * + * interfaceName: interface name, default is 'eth' on linux, 'en' on mac os. + */ +export function address(callback: AddressCallback): void; +export function address(interfaceName: string, callback: AddressCallback): void; +export function address(interfaceNameOrCallback: string | AddressCallback, callback?: AddressCallback) { + let interfaceName: string | undefined; + if (typeof interfaceNameOrCallback === 'function') { + callback = interfaceNameOrCallback; + } else { + interfaceName = interfaceNameOrCallback; + } + + const addr: Address = { + ip: ip(interfaceName), + ipv6: ipv6(interfaceName), + mac: undefined, + }; + mac(interfaceName || '', (err?: Error | null, mac?: string | null) => { + if (mac) { + addr.mac = mac; + } + callback!(err || null, addr); + }); +} diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..9b808c2 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,4 @@ +import { address } from './address.js'; + +export * from './address.js'; +export default address; diff --git a/src/promises.ts b/src/promises.ts new file mode 100644 index 0000000..04b9451 --- /dev/null +++ b/src/promises.ts @@ -0,0 +1,32 @@ +import { + Address, address as getAddress, + mac as getMac, + dns as getDns, +} from './address.js'; + +export function address(interfaceName?: string) { + return new Promise
((resolve, reject) => { + getAddress(interfaceName || '', (err, address) => { + if (err) return reject(err); + resolve(address); + }); + }); +} + +export function mac(interfaceName?: string) { + return new Promise((resolve, reject) => { + getMac(interfaceName || '', (err, address) => { + if (err) return reject(err); + resolve(address || null); + }); + }); +} + +export function dns(filepath?: string) { + return new Promise((resolve, reject) => { + getDns(filepath || '', (err, servers) => { + if (err) return reject(err); + resolve(servers || []); + }); + }); +} diff --git a/test/address.test.js b/test/address.test.ts similarity index 53% rename from test/address.test.js rename to test/address.test.ts index 583ab35..9159e5b 100644 --- a/test/address.test.js +++ b/test/address.test.ts @@ -1,98 +1,112 @@ -'use strict'; - -const assert = require('assert'); -const os = require('os'); -const child = require('child_process'); -const path = require('path'); -const mm = require('mm'); -const fs = require('fs'); -const address = require('..'); +import { strict as assert } from 'node:assert'; +import os from 'node:os'; +import child from 'node:child_process'; +import path from 'node:path'; +import fs from 'node:fs'; +import { fileURLToPath } from 'node:url'; +import mm from 'mm'; +import * as addressAll from '../src/index.js'; +import address from '../src/index.js'; +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); const fixtures = path.join(__dirname, 'fixtures'); -describe('test/address.test.js', () => { +describe('test/address.test.ts', () => { beforeEach(mm.restore); afterEach(mm.restore); describe('regex check', () => { it('should MAC_IP_RE pass', () => { - assert(address.MAC_IP_RE.test(' inet 10.7.84.211 netmask 0xfffffc00 broadcast 10.7.87.255')); - assert(address.MAC_IP_RE.test(' inet addr:10.125.5.202 Bcast:10.125.15.255 Mask:255.255.240.0')); + assert(addressAll.MAC_IP_RE.test(' inet 10.7.84.211 netmask 0xfffffc00 broadcast 10.7.87.255')); + assert(addressAll.MAC_IP_RE.test(' inet addr:10.125.5.202 Bcast:10.125.15.255 Mask:255.255.240.0')); }); it('should MAC_RE pass', () => { - assert(address.MAC_RE.test(' ether c4:2c:03:32:d5:3d ')); - assert(address.MAC_RE.test('eth0 Link encap:Ethernet HWaddr 00:16:3E:00:0A:29 ')); + assert(addressAll.MAC_RE.test(' ether c4:2c:03:32:d5:3d ')); + assert(addressAll.MAC_RE.test('eth0 Link encap:Ethernet HWaddr 00:16:3E:00:0A:29 ')); }); }); describe('address()', () => { - it('should return first ethernet addrs', done => { + it('should return first ethernet addresses', done => { address((err, addr) => { assert(!err); - assert.deepStrictEqual(Object.keys(addr), [ 'ip', 'ipv6', 'mac' ]); + assert.deepEqual(Object.keys(addr), [ 'ip', 'ipv6', 'mac' ]); addr.mac && assert.match(addr.mac, /^(?:[a-z0-9]{2}\:){5}[a-z0-9]{2}$/i); addr.ip && assert.match(addr.ip, /^\d+\.\d+\.\d+\.\d+$/); done(); }); }); - it('should return first ethernet addrs from osx', done => { - mm(address, 'interface', () => { - return { address: '192.168.2.104' }; + it('should return first ethernet addresses from osx', done => { + mm(os, 'networkInterfaces', () => { + return { + en1: [ + { address: '192.168.2.104', family: 'IPv4' }, + ], + }; }); mm.data(child, 'exec', fs.readFileSync(path.join(fixtures, 'darwin.txt'), 'utf8')); address('en', (err, addr) => { assert(!err); - assert.deepStrictEqual(Object.keys(addr), [ 'ip', 'ipv6', 'mac' ]); - assert.strictEqual(addr.ip, '192.168.2.104'); - assert.strictEqual(addr.mac, '78:ca:39:b0:e6:7d'); + assert.deepEqual(Object.keys(addr), [ 'ip', 'ipv6', 'mac' ]); + assert.equal(addr.ip, '192.168.2.104'); + assert.equal(addr.mac, '78:ca:39:b0:e6:7d'); done(); }); }); - it('should return first ethernet addrs from linux', done => { - mm(address, 'interface', () => { - return { address: '10.125.5.202' }; + it('should return first ethernet addresses from linux', done => { + mm(os, 'networkInterfaces', () => { + return { + eth: [ + { address: '10.125.5.202', family: 'IPv4' }, + ], + }; }); mm.data(child, 'exec', fs.readFileSync(path.join(fixtures, 'linux.txt'), 'utf8')); address('eth', (err, addr) => { assert(!err); - assert.deepStrictEqual(Object.keys(addr), [ 'ip', 'ipv6', 'mac' ]); - assert.strictEqual(addr.ip, '10.125.5.202'); - assert.strictEqual(addr.mac, '00:16:3E:00:0A:29'); + assert.deepEqual(Object.keys(addr), [ 'ip', 'ipv6', 'mac' ]); + assert.equal(addr.ip, '10.125.5.202'); + assert.equal(addr.mac, '00:16:3E:00:0A:29'); done(); }); }); - it('should return first vnic interface addrs from osx', done => { - mm(address, 'ip', () => { - return '10.211.55.2'; + it('should return first vnic interface addresses from osx', done => { + mm(os, 'networkInterfaces', () => { + return { + vnic: [ + { address: '10.211.55.2', family: 'IPv4' }, + ], + }; }); mm.data(child, 'exec', fs.readFileSync(path.join(fixtures, 'darwin.txt'), 'utf8')); address('vnic', (err, addr) => { assert(!err); - assert.strictEqual(addr.ip, '10.211.55.2'); + assert.equal(addr.ip, '10.211.55.2'); assert(!addr.ipv6); done(); }); }); - it('should return first local loopback addrs', done => { + it('should return first local loopback addresses', done => { address('lo', (err, addr) => { assert(!err); - assert.deepStrictEqual(Object.keys(addr), [ 'ip', 'ipv6', 'mac' ]); - assert.strictEqual(addr.ip, '127.0.0.1'); + assert.deepEqual(Object.keys(addr), [ 'ip', 'ipv6', 'mac' ]); + assert.equal(addr.ip, '127.0.0.1'); done(); }); }); - it('should return first local loopback addrs from linux', done => { + it('should return first local loopback addresses from linux', done => { mm.data(child, 'exec', fs.readFileSync(path.join(fixtures, 'linux.txt'), 'utf8')); address('lo', (err, addr) => { assert(!err); - assert.deepStrictEqual(Object.keys(addr), [ 'ip', 'ipv6', 'mac' ]); - assert.strictEqual(addr.ip, '127.0.0.1'); + assert.deepEqual(Object.keys(addr), [ 'ip', 'ipv6', 'mac' ]); + assert.equal(addr.ip, '127.0.0.1'); done(); }); }); @@ -100,7 +114,9 @@ describe('test/address.test.js', () => { describe('interface()', () => { it('should return interface with family', () => { - const item = address.interface(); + // interface rename to getInterfaceAddress + // const item = addressAll.interface(); + const item = addressAll.getInterfaceAddress(); assert(item); assert(item.address); assert(item.family); @@ -108,8 +124,8 @@ describe('test/address.test.js', () => { }); describe('address.mac()', () => { - it.skip('should return mac', done => { - address.mac((err, mac) => { + it('should return mac', done => { + addressAll.mac((err, mac) => { assert(!err); assert(mac); assert.match(mac, /(?:[a-z0-9]{2}\:){5}[a-z0-9]{2}/i); @@ -118,11 +134,18 @@ describe('test/address.test.js', () => { }); it('should return mock mac address', done => { - mm(address, 'interface', () => { - return { address: os.platform() === 'linux' ? '10.125.5.202' : '192.168.2.104' }; + mm(os, 'networkInterfaces', () => { + return { + en1: [ + { address: os.platform() === 'linux' ? '10.125.5.202' : '192.168.2.104', family: 'IPv4' }, + ], + eth1: [ + { address: os.platform() === 'linux' ? '10.125.5.202' : '192.168.2.104', family: 'IPv4' }, + ], + }; }); mm.data(child, 'exec', fs.readFileSync(path.join(fixtures, os.platform() + '.txt'), 'utf8')); - address.mac(os.platform() === 'linux' ? 'eth' : 'en', (err, mac) => { + addressAll.mac(os.platform() === 'linux' ? 'eth' : 'en', (err, mac) => { assert(!err); assert(mac); assert.match(mac, /(?:[a-z0-9]{2}\:){5}[a-z0-9]{2}/i); @@ -131,10 +154,10 @@ describe('test/address.test.js', () => { }); it('should return null when ip not exists', done => { - mm(address, 'interface', () => { - return null; + mm(os, 'networkInterfaces', () => { + return {}; }); - address.mac((err, mac) => { + addressAll.mac((err, mac) => { assert(!err); assert(!mac); done(); @@ -142,11 +165,11 @@ describe('test/address.test.js', () => { }); it('should return err when ifconfig cmd exec error', done => { - mm(address, 'interface', () => { - return null; + mm(os, 'networkInterfaces', () => { + return {}; }); mm.error(child, 'exec'); - address.mac((err, mac) => { + addressAll.mac((err, mac) => { assert(!err); assert(!mac); done(); @@ -158,22 +181,21 @@ describe('test/address.test.js', () => { return 'win32'; }); mm(os, 'networkInterfaces', () => { - return require(path.join(__dirname, './fixtures/win32_interfaces.json')); + return JSON.parse(fs.readFileSync(path.join(__dirname, './fixtures/win32_interfaces.json'), 'utf-8')); }); - address.mac((err, mac) => { + addressAll.mac((err, mac) => { assert(!err); assert(mac); - assert.strictEqual(mac, 'e8:2a:ea:8b:c2:20'); + assert.equal(mac, 'e8:2a:ea:8b:c2:20'); done(); }); }); - }); describe('address.ip()', () => { it('should return 127.0.0.1', () => { - assert.strictEqual(address.ip('lo'), '127.0.0.1'); + assert.equal(addressAll.ip('lo'), '127.0.0.1'); }); it('should return the first not 127.0.0.1 interface', () => { @@ -188,7 +210,7 @@ describe('test/address.test.js', () => { family: 'IPv4', internal: false }] }; }); - assert.strictEqual(address.ip(), '10.206.52.79'); + assert.equal(addressAll.ip(), '10.206.52.79'); }); it('should return utun1', () => { @@ -207,15 +229,15 @@ describe('test/address.test.js', () => { family: 'IPv4', internal: false }] }; }); - assert.strictEqual(address.ip('utun'), '10.206.52.79'); - assert.strictEqual(address.ipv6('utun'), 'fe80::696:ad3d:eeec:1722'); + assert.equal(addressAll.ip('utun'), '10.206.52.79'); + assert.equal(addressAll.ipv6('utun'), 'fe80::696:ad3d:eeec:1722'); }); }); describe('address.dns()', () => { it('should return dns servers from osx', done => { mm.data(fs, 'readFile', fs.readFileSync(path.join(fixtures, 'dns_darwin.txt'), 'utf8')); - address.dns((err, servers) => { + addressAll.dns((err, servers) => { assert(!err); assert(servers); assert(Array.isArray(servers)); @@ -226,7 +248,7 @@ describe('test/address.test.js', () => { it('should return dns servers from linux', done => { mm.data(fs, 'readFile', fs.readFileSync(path.join(fixtures, 'dns_linux.txt'), 'utf8')); - address.dns((err, servers) => { + addressAll.dns((err, servers) => { assert(!err); assert(servers); assert(Array.isArray(servers)); @@ -237,7 +259,7 @@ describe('test/address.test.js', () => { it('should return err when fs error', done => { mm.error(fs, 'readFile'); - address.dns((err, servers) => { + addressAll.dns((err, servers) => { assert(err); assert(!servers); done(); diff --git a/test/fixtures/ts/test.ts b/test/fixtures/ts/test.ts index d06e94a..7ad4acf 100644 --- a/test/fixtures/ts/test.ts +++ b/test/fixtures/ts/test.ts @@ -1,10 +1,10 @@ -import assert = require('assert'); +import assert from 'node:assert'; +import os from 'node:os'; +import mm from 'mm'; +import path from 'node:path'; +import child from 'node:child_process'; +import fs from 'node:fs'; import * as address from 'address'; -import * as os from 'os'; -import * as mm from 'mm'; -import * as path from 'path'; -import * as child from 'child_process'; -import * as fs from 'fs'; mm(address, 'interface', () => ({ address: os.platform() === 'linux' ? '10.125.5.202' : '192.168.2.104' })); mm.data(child, 'exec', fs.readFileSync(path.join(__dirname, `../${os.platform() + '.txt'}`), 'utf8')); @@ -39,7 +39,7 @@ address.mac(interfaceName, (err, mac) => { assert(mac.substring(0)); }); -address(interfaceName, (err, addr) => { +address.address(interfaceName, (err, addr) => { assert(!err); assert(addr.ip); assert(addr.ip.substring(0)); @@ -49,7 +49,7 @@ address(interfaceName, (err, addr) => { assert(addr.mac.substring(0)); }); -address((err, addr) => { +address.address((err, addr) => { assert(!err); assert(addr.ip); assert(addr.ip.substring(0)); diff --git a/test/fixtures/ts/tsconfig.json b/test/fixtures/ts/tsconfig.json index 785e1d3..c2b3d40 100644 --- a/test/fixtures/ts/tsconfig.json +++ b/test/fixtures/ts/tsconfig.json @@ -1,4 +1,5 @@ { + "extends": "@eggjs/tsconfig", "compilerOptions": { "target": "es5", "baseUrl": ".", @@ -9,6 +10,7 @@ }, "module": "commonjs", "strict": true, - "noImplicitAny": false + "noImplicitAny": false, + "declaration": false } -} \ No newline at end of file +} diff --git a/test/promises.test.ts b/test/promises.test.ts new file mode 100644 index 0000000..e77385b --- /dev/null +++ b/test/promises.test.ts @@ -0,0 +1,22 @@ +import { strict as assert } from 'node:assert'; +import { address, mac, dns } from '../src/promises.js'; + +describe('test/promises.test.ts', () => { + it('should address work', async () => { + const addr = await address(); + assert(addr.ip); + assert(addr.ipv6); + assert(addr.mac); + }); + + it('should mac work', async () => { + const addr = await mac(); + assert(addr); + }); + + it('should dns work', async () => { + const servers = await dns(); + assert(servers); + assert(servers.length > 0); + }); +}); diff --git a/test/ts.test.js b/test/ts.test.js deleted file mode 100644 index 5a5597c..0000000 --- a/test/ts.test.js +++ /dev/null @@ -1,13 +0,0 @@ -const runscript = require('runscript'); -const path = require('path'); - -describe('test/ts.test.js', () => { - it('should works with ts without error', done => { - const cwd = path.resolve(__dirname, './fixtures/ts'); - const tsconfigPath = path.resolve(cwd, 'tsconfig.json'); - const testFile = path.resolve(cwd, 'test'); - runscript(`tsc -p ${tsconfigPath} && node ${testFile}`, { stdio: 'inherit' }) - .then(() => done()) - .catch(done); - }); -}); diff --git a/test/ts.test.ts b/test/ts.test.ts new file mode 100644 index 0000000..964ea1f --- /dev/null +++ b/test/ts.test.ts @@ -0,0 +1,16 @@ +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import runscript from 'runscript'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +describe('test/ts.test.ts', () => { + it('should works with ts without error', done => { + const cwd = path.join(__dirname, './fixtures/ts'); + const tsconfigPath = path.join(cwd, 'tsconfig.json'); + runscript(`tsc -p ${tsconfigPath}`, { stdio: 'inherit' }) + .then(() => done()) + .catch(done); + }); +}); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..ff41b73 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "@eggjs/tsconfig", + "compilerOptions": { + "strict": true, + "noImplicitAny": true, + "target": "ES2022", + "module": "NodeNext", + "moduleResolution": "NodeNext" + } +}