fix(client,testing,build): improve TypeScript compatibility for DNS client parsing and test suite
This commit is contained in:
@@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"@git.zone/tsrust": {
|
||||||
|
"targets": [
|
||||||
|
"linux_amd64",
|
||||||
|
"linux_arm64"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"@git.zone/cli": {
|
||||||
|
"projectType": "npm",
|
||||||
|
"module": {
|
||||||
|
"githost": "code.foss.global",
|
||||||
|
"gitscope": "push.rocks",
|
||||||
|
"gitrepo": "smartdns",
|
||||||
|
"description": "A robust TypeScript library providing advanced DNS management and resolution capabilities including support for DNSSEC, custom DNS servers, and integration with various DNS providers.",
|
||||||
|
"npmPackagename": "@push.rocks/smartdns",
|
||||||
|
"license": "MIT",
|
||||||
|
"projectDomain": "push.rocks"
|
||||||
|
},
|
||||||
|
"release": {
|
||||||
|
"registries": [
|
||||||
|
"https://verdaccio.lossless.digital",
|
||||||
|
"https://registry.npmjs.org"
|
||||||
|
],
|
||||||
|
"accessLevel": "public"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@git.zone/tsdoc": {
|
||||||
|
"legal": "\n## License and Legal Information\n\nThis repository contains open-source code that is licensed under the MIT License. A copy of the MIT License can be found in the [license](license) file within this repository. \n\n**Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.\n\n### Trademarks\n\nThis project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH and are not included within the scope of the MIT license granted herein. Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines, and any usage must be approved in writing by Task Venture Capital GmbH.\n\n### Company Information\n\nTask Venture Capital GmbH \nRegistered at District court Bremen HRB 35230 HB, Germany\n\nFor any legal inquiries or if you require further information, please contact us via email at hello@task.vc.\n\nBy using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.\n"
|
||||||
|
},
|
||||||
|
"@ship.zone/szci": {
|
||||||
|
"npmGlobalTools": [],
|
||||||
|
"npmRegistryUrl": "registry.npmjs.org"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,13 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 2026-04-30 - 7.9.1 - fix(client,testing,build)
|
||||||
|
improve TypeScript compatibility for DNS client parsing and test suite
|
||||||
|
|
||||||
|
- fix TXT record value parsing in the DNS client by normalizing array-based resolver results into strings
|
||||||
|
- tighten TypeScript configuration with noImplicitAny and explicit Node types
|
||||||
|
- update tests to use the current tstest server-side API and add stricter null-safe typings for decoded DNS answers and server lifecycle handling
|
||||||
|
- refresh build and package metadata, including dependency upgrades and published config files
|
||||||
|
|
||||||
## 2026-02-20 - 7.9.0 - feat(server)
|
## 2026-02-20 - 7.9.0 - feat(server)
|
||||||
emit query events with questions, answered status, response time and timestamp
|
emit query events with questions, answered status, response time and timestamp
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2016 Push.Rocks
|
||||||
|
|
||||||
|
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:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
+13
-10
@@ -10,7 +10,7 @@
|
|||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "(tstest test/ --verbose --timeout 60)",
|
"test": "(tstest test/ --verbose --timeout 60)",
|
||||||
"build": "(tsbuild tsfolders --web --allowimplicitany) && (tsrust)",
|
"build": "(tsbuild tsfolders --web) && (tsrust)",
|
||||||
"buildDocs": "tsdoc"
|
"buildDocs": "tsdoc"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
@@ -46,18 +46,19 @@
|
|||||||
"@push.rocks/smartdelay": "^3.0.1",
|
"@push.rocks/smartdelay": "^3.0.1",
|
||||||
"@push.rocks/smartenv": "^6.0.0",
|
"@push.rocks/smartenv": "^6.0.0",
|
||||||
"@push.rocks/smartpromise": "^4.2.3",
|
"@push.rocks/smartpromise": "^4.2.3",
|
||||||
"@push.rocks/smartrust": "^1.2.1",
|
"@push.rocks/smartrust": "^1.4.0",
|
||||||
"@tsclass/tsclass": "^9.3.0",
|
"@tsclass/tsclass": "^9.5.1",
|
||||||
"acme-client": "^5.4.0",
|
"acme-client": "^5.4.0",
|
||||||
"minimatch": "^10.2.0"
|
"minimatch": "^10.2.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@git.zone/tsbuild": "^4.1.2",
|
"@git.zone/tsbuild": "^4.4.0",
|
||||||
"@git.zone/tsrun": "^2.0.1",
|
"@git.zone/tsrun": "^2.0.2",
|
||||||
"@git.zone/tsrust": "^1.3.0",
|
"@git.zone/tsrust": "^1.3.2",
|
||||||
"@git.zone/tstest": "^3.1.8",
|
"@git.zone/tstest": "^3.6.3",
|
||||||
"@types/dns-packet": "^5.6.5",
|
"@types/dns-packet": "^5.6.5",
|
||||||
"@types/node": "^25.2.3",
|
"@types/lodash.clonedeep": "^4.5.9",
|
||||||
|
"@types/node": "^25.6.0",
|
||||||
"dns-packet": "^5.6.1"
|
"dns-packet": "^5.6.1"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
@@ -69,6 +70,8 @@
|
|||||||
"dist_ts_web/**/*",
|
"dist_ts_web/**/*",
|
||||||
"assets/**/*",
|
"assets/**/*",
|
||||||
"cli.js",
|
"cli.js",
|
||||||
|
".smartconfig.json",
|
||||||
|
"license",
|
||||||
"npmextra.json",
|
"npmextra.json",
|
||||||
"readme.md"
|
"readme.md"
|
||||||
],
|
],
|
||||||
@@ -76,5 +79,5 @@
|
|||||||
"last 1 chrome versions"
|
"last 1 chrome versions"
|
||||||
],
|
],
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"packageManager": "pnpm@10.10.0+sha512.d615db246fe70f25dcfea6d8d73dee782ce23e2245e3c4f6f888249fb568149318637dca73c2c5c8ef2a4ca0d5657fb9567188bfab47f566d1ee6ce987815c39"
|
"packageManager": "pnpm@10.28.2"
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
+1693
-3279
File diff suppressed because it is too large
Load Diff
@@ -1,12 +1,14 @@
|
|||||||
import * as plugins from '../ts_server/plugins.js';
|
import * as plugins from '../ts_server/plugins.js';
|
||||||
import { expect, tap } from '@git.zone/tstest/tapbundle';
|
import { expect, tap } from '@git.zone/tstest/tapbundle';
|
||||||
import { tapNodeTools } from '@git.zone/tstest/tapbundle_serverside';
|
import { TapNodeTools } from '@git.zone/tstest/tapbundle_serverside';
|
||||||
import * as dnsPacket from 'dns-packet';
|
import * as dnsPacket from 'dns-packet';
|
||||||
import * as dgram from 'dgram';
|
import * as dgram from 'dgram';
|
||||||
|
|
||||||
import * as smartdns from '../ts_server/index.js';
|
import * as smartdns from '../ts_server/index.js';
|
||||||
|
|
||||||
let dnsServer: smartdns.DnsServer;
|
const tapNodeTools = new TapNodeTools(tap);
|
||||||
|
|
||||||
|
let dnsServer: smartdns.DnsServer | null;
|
||||||
|
|
||||||
// Port management for tests
|
// Port management for tests
|
||||||
let nextHttpsPort = 8500;
|
let nextHttpsPort = 8500;
|
||||||
@@ -29,7 +31,7 @@ async function stopServer(server: smartdns.DnsServer | null | undefined) {
|
|||||||
try {
|
try {
|
||||||
await server.stop();
|
await server.stop();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log('Handled error when stopping server:', e.message || e);
|
console.log('Handled error when stopping server:', e instanceof Error ? e.message : e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,8 +128,8 @@ tap.test('DNSSEC should sign entire RRset together, not individual records', asy
|
|||||||
const dnsResponse = await responsePromise;
|
const dnsResponse = await responsePromise;
|
||||||
|
|
||||||
// Count NS and RRSIG records
|
// Count NS and RRSIG records
|
||||||
const nsAnswers = dnsResponse.answers.filter(a => a.type === 'NS');
|
const nsAnswers = dnsResponse.answers!.filter(a => a.type === 'NS');
|
||||||
const rrsigAnswers = dnsResponse.answers.filter(a => a.type === 'RRSIG');
|
const rrsigAnswers = dnsResponse.answers!.filter(a => a.type === 'RRSIG');
|
||||||
|
|
||||||
console.log('NS records returned:', nsAnswers.length);
|
console.log('NS records returned:', nsAnswers.length);
|
||||||
console.log('RRSIG records returned:', rrsigAnswers.length);
|
console.log('RRSIG records returned:', rrsigAnswers.length);
|
||||||
@@ -197,7 +199,7 @@ tap.test('SOA records should be properly serialized and returned', async () => {
|
|||||||
const dnsResponse = await responsePromise;
|
const dnsResponse = await responsePromise;
|
||||||
|
|
||||||
// Should have SOA record in response
|
// Should have SOA record in response
|
||||||
const soaAnswers = dnsResponse.answers.filter(a => a.type === 'SOA');
|
const soaAnswers = dnsResponse.answers!.filter(a => a.type === 'SOA');
|
||||||
expect(soaAnswers.length).toEqual(1);
|
expect(soaAnswers.length).toEqual(1);
|
||||||
|
|
||||||
const soaData = (soaAnswers[0] as any).data;
|
const soaData = (soaAnswers[0] as any).data;
|
||||||
@@ -269,7 +271,7 @@ tap.test('Primary nameserver should be configurable', async () => {
|
|||||||
const dnsResponse = await responsePromise;
|
const dnsResponse = await responsePromise;
|
||||||
|
|
||||||
// Should have SOA record with custom nameserver
|
// Should have SOA record with custom nameserver
|
||||||
const soaAnswers = dnsResponse.answers.filter(a => a.type === 'SOA');
|
const soaAnswers = dnsResponse.answers!.filter(a => a.type === 'SOA');
|
||||||
expect(soaAnswers.length).toEqual(1);
|
expect(soaAnswers.length).toEqual(1);
|
||||||
|
|
||||||
const soaData = (soaAnswers[0] as any).data;
|
const soaData = (soaAnswers[0] as any).data;
|
||||||
@@ -356,8 +358,8 @@ tap.test('Multiple A records should have single RRSIG when DNSSEC is enabled', a
|
|||||||
|
|
||||||
const dnsResponse = await responsePromise;
|
const dnsResponse = await responsePromise;
|
||||||
|
|
||||||
const aAnswers = dnsResponse.answers.filter(a => a.type === 'A');
|
const aAnswers = dnsResponse.answers!.filter(a => a.type === 'A');
|
||||||
const rrsigAnswers = dnsResponse.answers.filter(a => a.type === 'RRSIG');
|
const rrsigAnswers = dnsResponse.answers!.filter(a => a.type === 'RRSIG');
|
||||||
|
|
||||||
console.log('A records:', aAnswers.length);
|
console.log('A records:', aAnswers.length);
|
||||||
console.log('RRSIG records:', rrsigAnswers.length);
|
console.log('RRSIG records:', rrsigAnswers.length);
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
import * as plugins from '../ts_server/plugins.js';
|
import * as plugins from '../ts_server/plugins.js';
|
||||||
import { expect, tap } from '@git.zone/tstest/tapbundle';
|
import { expect, tap } from '@git.zone/tstest/tapbundle';
|
||||||
import { tapNodeTools } from '@git.zone/tstest/tapbundle_serverside';
|
import { TapNodeTools } from '@git.zone/tstest/tapbundle_serverside';
|
||||||
import * as dnsPacket from 'dns-packet';
|
import * as dnsPacket from 'dns-packet';
|
||||||
import * as dgram from 'dgram';
|
import * as dgram from 'dgram';
|
||||||
|
|
||||||
import * as smartdns from '../ts_server/index.js';
|
import * as smartdns from '../ts_server/index.js';
|
||||||
|
|
||||||
let dnsServer: smartdns.DnsServer;
|
const tapNodeTools = new TapNodeTools(tap);
|
||||||
|
|
||||||
|
let dnsServer: smartdns.DnsServer | null;
|
||||||
|
|
||||||
// Port management for tests
|
// Port management for tests
|
||||||
let nextHttpsPort = 8600;
|
let nextHttpsPort = 8600;
|
||||||
@@ -29,7 +31,7 @@ async function stopServer(server: smartdns.DnsServer | null | undefined) {
|
|||||||
try {
|
try {
|
||||||
await server.stop();
|
await server.stop();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log('Handled error when stopping server:', e.message || e);
|
console.log('Handled error when stopping server:', e instanceof Error ? e.message : e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,7 +87,7 @@ tap.test('SOA records should be returned for non-existent domains', async () =>
|
|||||||
const dnsResponse = await responsePromise;
|
const dnsResponse = await responsePromise;
|
||||||
|
|
||||||
console.log('✅ SOA response received');
|
console.log('✅ SOA response received');
|
||||||
const soaAnswers = dnsResponse.answers.filter(a => a.type === 'SOA');
|
const soaAnswers = dnsResponse.answers!.filter(a => a.type === 'SOA');
|
||||||
expect(soaAnswers.length).toEqual(1);
|
expect(soaAnswers.length).toEqual(1);
|
||||||
|
|
||||||
const soaData = (soaAnswers[0] as any).data;
|
const soaData = (soaAnswers[0] as any).data;
|
||||||
@@ -151,7 +153,7 @@ tap.test('Primary nameserver should be configurable', async () => {
|
|||||||
|
|
||||||
const dnsResponse = await responsePromise;
|
const dnsResponse = await responsePromise;
|
||||||
|
|
||||||
const soaAnswers = dnsResponse.answers.filter(a => a.type === 'SOA');
|
const soaAnswers = dnsResponse.answers!.filter(a => a.type === 'SOA');
|
||||||
expect(soaAnswers.length).toEqual(1);
|
expect(soaAnswers.length).toEqual(1);
|
||||||
|
|
||||||
const soaData = (soaAnswers[0] as any).data;
|
const soaData = (soaAnswers[0] as any).data;
|
||||||
@@ -215,7 +217,7 @@ tap.test('Default primary nameserver with FQDN', async () => {
|
|||||||
|
|
||||||
const dnsResponse = await responsePromise;
|
const dnsResponse = await responsePromise;
|
||||||
|
|
||||||
const soaAnswers = dnsResponse.answers.filter(a => a.type === 'SOA');
|
const soaAnswers = dnsResponse.answers!.filter(a => a.type === 'SOA');
|
||||||
const soaData = (soaAnswers[0] as any).data;
|
const soaData = (soaAnswers[0] as any).data;
|
||||||
console.log('✅ FQDN primary nameserver:', soaData.mname);
|
console.log('✅ FQDN primary nameserver:', soaData.mname);
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
import * as plugins from '../ts_server/plugins.js';
|
import * as plugins from '../ts_server/plugins.js';
|
||||||
import { expect, tap } from '@git.zone/tstest/tapbundle';
|
import { expect, tap } from '@git.zone/tstest/tapbundle';
|
||||||
import { tapNodeTools } from '@git.zone/tstest/tapbundle_serverside';
|
import { TapNodeTools } from '@git.zone/tstest/tapbundle_serverside';
|
||||||
import * as dnsPacket from 'dns-packet';
|
import * as dnsPacket from 'dns-packet';
|
||||||
import * as dgram from 'dgram';
|
import * as dgram from 'dgram';
|
||||||
|
|
||||||
import * as smartdns from '../ts_server/index.js';
|
import * as smartdns from '../ts_server/index.js';
|
||||||
|
|
||||||
let dnsServer: smartdns.DnsServer;
|
const tapNodeTools = new TapNodeTools(tap);
|
||||||
|
|
||||||
|
let dnsServer: smartdns.DnsServer | null;
|
||||||
|
|
||||||
// Port management for tests
|
// Port management for tests
|
||||||
let nextHttpsPort = 8300;
|
let nextHttpsPort = 8300;
|
||||||
@@ -34,7 +36,7 @@ async function stopServer(server: smartdns.DnsServer | null | undefined) {
|
|||||||
|
|
||||||
await Promise.race([stopPromise, timeoutPromise]);
|
await Promise.race([stopPromise, timeoutPromise]);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log('Handled error when stopping server:', e.message || e);
|
console.log('Handled error when stopping server:', e instanceof Error ? e.message : e);
|
||||||
|
|
||||||
// Force close if normal stop fails
|
// Force close if normal stop fails
|
||||||
try {
|
try {
|
||||||
@@ -49,7 +51,7 @@ async function stopServer(server: smartdns.DnsServer | null | undefined) {
|
|||||||
(server as any).udpServer = null;
|
(server as any).udpServer = null;
|
||||||
}
|
}
|
||||||
} catch (forceError) {
|
} catch (forceError) {
|
||||||
console.log('Force cleanup error:', forceError.message || forceError);
|
console.log('Force cleanup error:', forceError instanceof Error ? forceError.message : forceError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -128,13 +130,13 @@ tap.test('should now return multiple NS records after fix', async () => {
|
|||||||
|
|
||||||
const dnsResponse = await responsePromise;
|
const dnsResponse = await responsePromise;
|
||||||
|
|
||||||
console.log('Fixed behavior - NS records returned:', dnsResponse.answers.length);
|
console.log('Fixed behavior - NS records returned:', dnsResponse.answers!.length);
|
||||||
console.log('NS records:', dnsResponse.answers.filter(a => a.type === 'NS').map(a => a.data));
|
console.log('NS records:', dnsResponse.answers!.filter(a => a.type === 'NS').map(a => (a as any).data));
|
||||||
|
|
||||||
// FIXED BEHAVIOR: Should now return both NS records
|
// FIXED BEHAVIOR: Should now return both NS records
|
||||||
const nsAnswers = dnsResponse.answers.filter(a => a.type === 'NS');
|
const nsAnswers = dnsResponse.answers!.filter(a => a.type === 'NS');
|
||||||
expect(nsAnswers.length).toEqual(2);
|
expect(nsAnswers.length).toEqual(2);
|
||||||
expect(nsAnswers.map(a => a.data).sort()).toEqual(['ns1.example.com', 'ns2.example.com']);
|
expect(nsAnswers.map(a => (a as any).data).sort()).toEqual(['ns1.example.com', 'ns2.example.com']);
|
||||||
|
|
||||||
await stopServer(dnsServer);
|
await stopServer(dnsServer);
|
||||||
dnsServer = null;
|
dnsServer = null;
|
||||||
@@ -206,13 +208,13 @@ tap.test('should support round-robin DNS with multiple A records', async () => {
|
|||||||
|
|
||||||
const dnsResponse = await responsePromise;
|
const dnsResponse = await responsePromise;
|
||||||
|
|
||||||
console.log('Fixed behavior - A records returned:', dnsResponse.answers.length);
|
console.log('Fixed behavior - A records returned:', dnsResponse.answers!.length);
|
||||||
console.log('A records:', dnsResponse.answers.filter(a => a.type === 'A').map(a => a.data));
|
console.log('A records:', dnsResponse.answers!.filter(a => a.type === 'A').map(a => (a as any).data));
|
||||||
|
|
||||||
// FIXED BEHAVIOR: Should return all A records for round-robin
|
// FIXED BEHAVIOR: Should return all A records for round-robin
|
||||||
const aAnswers = dnsResponse.answers.filter(a => a.type === 'A');
|
const aAnswers = dnsResponse.answers!.filter(a => a.type === 'A');
|
||||||
expect(aAnswers.length).toEqual(3);
|
expect(aAnswers.length).toEqual(3);
|
||||||
expect(aAnswers.map(a => a.data).sort()).toEqual(['10.0.0.1', '10.0.0.2', '10.0.0.3']);
|
expect(aAnswers.map(a => (a as any).data).sort()).toEqual(['10.0.0.1', '10.0.0.2', '10.0.0.3']);
|
||||||
|
|
||||||
await stopServer(dnsServer);
|
await stopServer(dnsServer);
|
||||||
dnsServer = null;
|
dnsServer = null;
|
||||||
@@ -289,8 +291,8 @@ tap.test('should return multiple TXT records', async () => {
|
|||||||
|
|
||||||
const dnsResponse = await responsePromise;
|
const dnsResponse = await responsePromise;
|
||||||
|
|
||||||
console.log('Fixed behavior - TXT records returned:', dnsResponse.answers.length);
|
console.log('Fixed behavior - TXT records returned:', dnsResponse.answers!.length);
|
||||||
const txtAnswers = dnsResponse.answers.filter(a => a.type === 'TXT');
|
const txtAnswers = dnsResponse.answers!.filter(a => a.type === 'TXT');
|
||||||
console.log('TXT records count:', txtAnswers.length);
|
console.log('TXT records count:', txtAnswers.length);
|
||||||
|
|
||||||
// FIXED BEHAVIOR: Should return all TXT records
|
// FIXED BEHAVIOR: Should return all TXT records
|
||||||
@@ -388,10 +390,10 @@ tap.test('should handle DNSSEC correctly with multiple records', async () => {
|
|||||||
|
|
||||||
const dnsResponse = await responsePromise;
|
const dnsResponse = await responsePromise;
|
||||||
|
|
||||||
console.log('DNSSEC response - total answers:', dnsResponse.answers.length);
|
console.log('DNSSEC response - total answers:', dnsResponse.answers!.length);
|
||||||
|
|
||||||
const nsAnswers = dnsResponse.answers.filter(a => a.type === 'NS');
|
const nsAnswers = dnsResponse.answers!.filter(a => a.type === 'NS');
|
||||||
const rrsigAnswers = dnsResponse.answers.filter(a => a.type === 'RRSIG');
|
const rrsigAnswers = dnsResponse.answers!.filter(a => a.type === 'RRSIG');
|
||||||
|
|
||||||
console.log('NS records:', nsAnswers.length);
|
console.log('NS records:', nsAnswers.length);
|
||||||
console.log('RRSIG records:', rrsigAnswers.length);
|
console.log('RRSIG records:', rrsigAnswers.length);
|
||||||
@@ -417,7 +419,7 @@ tap.test('should not return duplicate records when same handler registered multi
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Register the same handler multiple times (edge case)
|
// Register the same handler multiple times (edge case)
|
||||||
const sameHandler = (question) => {
|
const sameHandler = (question: smartdns.IDnsQuestion) => {
|
||||||
return {
|
return {
|
||||||
name: question.name,
|
name: question.name,
|
||||||
type: 'A',
|
type: 'A',
|
||||||
@@ -470,13 +472,13 @@ tap.test('should not return duplicate records when same handler registered multi
|
|||||||
|
|
||||||
const dnsResponse = await responsePromise;
|
const dnsResponse = await responsePromise;
|
||||||
|
|
||||||
const aAnswers = dnsResponse.answers.filter(a => a.type === 'A');
|
const aAnswers = dnsResponse.answers!.filter(a => a.type === 'A');
|
||||||
console.log('Duplicate handler test - A records returned:', aAnswers.length);
|
console.log('Duplicate handler test - A records returned:', aAnswers.length);
|
||||||
|
|
||||||
// Even though handler is registered 3 times, we get 3 identical records
|
// Even though handler is registered 3 times, we get 3 identical records
|
||||||
// This is expected behavior - the DNS server doesn't deduplicate
|
// This is expected behavior - the DNS server doesn't deduplicate
|
||||||
expect(aAnswers.length).toEqual(3);
|
expect(aAnswers.length).toEqual(3);
|
||||||
expect(aAnswers.every(a => a.data === '10.0.0.1')).toEqual(true);
|
expect(aAnswers.every(a => (a as any).data === '10.0.0.1')).toEqual(true);
|
||||||
|
|
||||||
await stopServer(dnsServer);
|
await stopServer(dnsServer);
|
||||||
dnsServer = null;
|
dnsServer = null;
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
import * as plugins from '../ts_server/plugins.js';
|
import * as plugins from '../ts_server/plugins.js';
|
||||||
import { expect, tap } from '@git.zone/tstest/tapbundle';
|
import { expect, tap } from '@git.zone/tstest/tapbundle';
|
||||||
import { tapNodeTools } from '@git.zone/tstest/tapbundle_serverside';
|
import { TapNodeTools } from '@git.zone/tstest/tapbundle_serverside';
|
||||||
import * as dnsPacket from 'dns-packet';
|
import * as dnsPacket from 'dns-packet';
|
||||||
import * as dgram from 'dgram';
|
import * as dgram from 'dgram';
|
||||||
|
|
||||||
import * as smartdns from '../ts_server/index.js';
|
import * as smartdns from '../ts_server/index.js';
|
||||||
|
|
||||||
let dnsServer: smartdns.DnsServer;
|
const tapNodeTools = new TapNodeTools(tap);
|
||||||
|
|
||||||
|
let dnsServer: smartdns.DnsServer | null;
|
||||||
|
|
||||||
// Port management for tests
|
// Port management for tests
|
||||||
let nextHttpsPort = 8400;
|
let nextHttpsPort = 8400;
|
||||||
@@ -29,7 +31,7 @@ async function stopServer(server: smartdns.DnsServer | null | undefined) {
|
|||||||
try {
|
try {
|
||||||
await server.stop();
|
await server.stop();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log('Handled error when stopping server:', e.message || e);
|
console.log('Handled error when stopping server:', e instanceof Error ? e.message : e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,12 +107,12 @@ tap.test('Multiple NS records should work correctly', async () => {
|
|||||||
|
|
||||||
const dnsResponse = await responsePromise;
|
const dnsResponse = await responsePromise;
|
||||||
|
|
||||||
console.log('✅ NS records returned:', dnsResponse.answers.length);
|
console.log('✅ NS records returned:', dnsResponse.answers!.length);
|
||||||
console.log('✅ NS records:', dnsResponse.answers.map(a => (a as any).data));
|
console.log('✅ NS records:', dnsResponse.answers!.map(a => (a as any).data));
|
||||||
|
|
||||||
// SUCCESS: Multiple NS records are now returned
|
// SUCCESS: Multiple NS records are now returned
|
||||||
expect(dnsResponse.answers.length).toEqual(2);
|
expect(dnsResponse.answers!.length).toEqual(2);
|
||||||
expect(dnsResponse.answers.map(a => (a as any).data).sort()).toEqual(['ns1.example.com', 'ns2.example.com']);
|
expect(dnsResponse.answers!.map(a => (a as any).data).sort()).toEqual(['ns1.example.com', 'ns2.example.com']);
|
||||||
|
|
||||||
await stopServer(dnsServer);
|
await stopServer(dnsServer);
|
||||||
dnsServer = null;
|
dnsServer = null;
|
||||||
@@ -181,12 +183,12 @@ tap.test('Multiple A records for round-robin DNS', async () => {
|
|||||||
|
|
||||||
const dnsResponse = await responsePromise;
|
const dnsResponse = await responsePromise;
|
||||||
|
|
||||||
console.log('✅ A records returned:', dnsResponse.answers.length);
|
console.log('✅ A records returned:', dnsResponse.answers!.length);
|
||||||
console.log('✅ A records:', dnsResponse.answers.map(a => (a as any).data));
|
console.log('✅ A records:', dnsResponse.answers!.map(a => (a as any).data));
|
||||||
|
|
||||||
// SUCCESS: All A records for round-robin DNS
|
// SUCCESS: All A records for round-robin DNS
|
||||||
expect(dnsResponse.answers.length).toEqual(3);
|
expect(dnsResponse.answers!.length).toEqual(3);
|
||||||
expect(dnsResponse.answers.map(a => (a as any).data).sort()).toEqual(['10.0.0.1', '10.0.0.2', '10.0.0.3']);
|
expect(dnsResponse.answers!.map(a => (a as any).data).sort()).toEqual(['10.0.0.1', '10.0.0.2', '10.0.0.3']);
|
||||||
|
|
||||||
await stopServer(dnsServer);
|
await stopServer(dnsServer);
|
||||||
dnsServer = null;
|
dnsServer = null;
|
||||||
@@ -262,12 +264,12 @@ tap.test('Multiple TXT records', async () => {
|
|||||||
|
|
||||||
const dnsResponse = await responsePromise;
|
const dnsResponse = await responsePromise;
|
||||||
|
|
||||||
console.log('✅ TXT records returned:', dnsResponse.answers.length);
|
console.log('✅ TXT records returned:', dnsResponse.answers!.length);
|
||||||
|
|
||||||
// SUCCESS: All TXT records are returned
|
// SUCCESS: All TXT records are returned
|
||||||
expect(dnsResponse.answers.length).toEqual(3);
|
expect(dnsResponse.answers!.length).toEqual(3);
|
||||||
|
|
||||||
const txtData = dnsResponse.answers.map(a => (a as any).data[0].toString());
|
const txtData = dnsResponse.answers!.map(a => (a as any).data[0].toString());
|
||||||
expect(txtData.some(d => d.includes('spf1'))).toEqual(true);
|
expect(txtData.some(d => d.includes('spf1'))).toEqual(true);
|
||||||
expect(txtData.some(d => d.includes('DKIM1'))).toEqual(true);
|
expect(txtData.some(d => d.includes('DKIM1'))).toEqual(true);
|
||||||
expect(txtData.some(d => d.includes('google-site-verification'))).toEqual(true);
|
expect(txtData.some(d => d.includes('google-site-verification'))).toEqual(true);
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
import * as plugins from '../ts_server/plugins.js';
|
import * as plugins from '../ts_server/plugins.js';
|
||||||
import { expect, tap } from '@git.zone/tstest/tapbundle';
|
import { expect, tap } from '@git.zone/tstest/tapbundle';
|
||||||
import { tapNodeTools } from '@git.zone/tstest/tapbundle_serverside';
|
import { TapNodeTools } from '@git.zone/tstest/tapbundle_serverside';
|
||||||
import * as dnsPacket from 'dns-packet';
|
import * as dnsPacket from 'dns-packet';
|
||||||
import * as dgram from 'dgram';
|
import * as dgram from 'dgram';
|
||||||
|
|
||||||
import * as smartdns from '../ts_server/index.js';
|
import * as smartdns from '../ts_server/index.js';
|
||||||
|
|
||||||
let dnsServer: smartdns.DnsServer;
|
const tapNodeTools = new TapNodeTools(tap);
|
||||||
|
|
||||||
|
let dnsServer: smartdns.DnsServer | null;
|
||||||
|
|
||||||
// Port management for tests
|
// Port management for tests
|
||||||
let nextHttpsPort = 8200;
|
let nextHttpsPort = 8200;
|
||||||
@@ -34,7 +36,7 @@ async function stopServer(server: smartdns.DnsServer | null | undefined) {
|
|||||||
|
|
||||||
await Promise.race([stopPromise, timeoutPromise]);
|
await Promise.race([stopPromise, timeoutPromise]);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log('Handled error when stopping server:', e.message || e);
|
console.log('Handled error when stopping server:', e instanceof Error ? e.message : e);
|
||||||
|
|
||||||
// Force close if normal stop fails
|
// Force close if normal stop fails
|
||||||
try {
|
try {
|
||||||
@@ -49,7 +51,7 @@ async function stopServer(server: smartdns.DnsServer | null | undefined) {
|
|||||||
(server as any).udpServer = null;
|
(server as any).udpServer = null;
|
||||||
}
|
}
|
||||||
} catch (forceError) {
|
} catch (forceError) {
|
||||||
console.log('Force cleanup error:', forceError.message || forceError);
|
console.log('Force cleanup error:', forceError instanceof Error ? forceError.message : forceError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -128,12 +130,12 @@ tap.test('should properly return multiple NS records', async () => {
|
|||||||
|
|
||||||
const dnsResponse = await responsePromise;
|
const dnsResponse = await responsePromise;
|
||||||
|
|
||||||
console.log('Current behavior - NS records returned:', dnsResponse.answers.length);
|
console.log('Current behavior - NS records returned:', dnsResponse.answers!.length);
|
||||||
console.log('NS records:', dnsResponse.answers.map(a => (a as any).data));
|
console.log('NS records:', dnsResponse.answers!.map(a => (a as any).data));
|
||||||
|
|
||||||
// Should return all registered NS records
|
// Should return all registered NS records
|
||||||
expect(dnsResponse.answers.length).toEqual(2);
|
expect(dnsResponse.answers!.length).toEqual(2);
|
||||||
const nsData = dnsResponse.answers.map(a => (a as any).data).sort();
|
const nsData = dnsResponse.answers!.map(a => (a as any).data).sort();
|
||||||
expect(nsData).toEqual(['ns1.example.com', 'ns2.example.com']);
|
expect(nsData).toEqual(['ns1.example.com', 'ns2.example.com']);
|
||||||
|
|
||||||
await stopServer(dnsServer);
|
await stopServer(dnsServer);
|
||||||
@@ -225,12 +227,12 @@ tap.test('should properly return multiple A records for round-robin DNS', async
|
|||||||
|
|
||||||
const dnsResponse = await responsePromise;
|
const dnsResponse = await responsePromise;
|
||||||
|
|
||||||
console.log('Current behavior - A records returned:', dnsResponse.answers.length);
|
console.log('Current behavior - A records returned:', dnsResponse.answers!.length);
|
||||||
console.log('A records:', dnsResponse.answers.map(a => (a as any).data));
|
console.log('A records:', dnsResponse.answers!.map(a => (a as any).data));
|
||||||
|
|
||||||
// Should return all registered A records for round-robin DNS
|
// Should return all registered A records for round-robin DNS
|
||||||
expect(dnsResponse.answers.length).toEqual(3);
|
expect(dnsResponse.answers!.length).toEqual(3);
|
||||||
const aData = dnsResponse.answers.map(a => (a as any).data).sort();
|
const aData = dnsResponse.answers!.map(a => (a as any).data).sort();
|
||||||
expect(aData).toEqual(['10.0.0.1', '10.0.0.2', '10.0.0.3']);
|
expect(aData).toEqual(['10.0.0.1', '10.0.0.2', '10.0.0.3']);
|
||||||
|
|
||||||
await stopServer(dnsServer);
|
await stopServer(dnsServer);
|
||||||
@@ -322,12 +324,12 @@ tap.test('should properly return multiple TXT records', async () => {
|
|||||||
|
|
||||||
const dnsResponse = await responsePromise;
|
const dnsResponse = await responsePromise;
|
||||||
|
|
||||||
console.log('Current behavior - TXT records returned:', dnsResponse.answers.length);
|
console.log('Current behavior - TXT records returned:', dnsResponse.answers!.length);
|
||||||
console.log('TXT records:', dnsResponse.answers.map(a => (a as any).data));
|
console.log('TXT records:', dnsResponse.answers!.map(a => (a as any).data));
|
||||||
|
|
||||||
// Should return all registered TXT records
|
// Should return all registered TXT records
|
||||||
expect(dnsResponse.answers.length).toEqual(3);
|
expect(dnsResponse.answers!.length).toEqual(3);
|
||||||
const txtData = dnsResponse.answers.map(a => (a as any).data[0]).sort();
|
const txtData = dnsResponse.answers!.map(a => (a as any).data[0]).sort();
|
||||||
expect(txtData[0]).toInclude('google-site-verification');
|
expect(txtData[0]).toInclude('google-site-verification');
|
||||||
expect(txtData[1]).toInclude('DKIM1');
|
expect(txtData[1]).toInclude('DKIM1');
|
||||||
expect(txtData[2]).toInclude('spf1');
|
expect(txtData[2]).toInclude('spf1');
|
||||||
@@ -408,14 +410,14 @@ tap.test('should rotate between records when using a single handler', async () =
|
|||||||
|
|
||||||
const [response1, response2] = await Promise.all([responsePromise1, responsePromise2]);
|
const [response1, response2] = await Promise.all([responsePromise1, responsePromise2]);
|
||||||
|
|
||||||
console.log('First query NS:', (response1.answers[0] as any).data);
|
console.log('First query NS:', (response1.answers![0] as any).data);
|
||||||
console.log('Second query NS:', (response2.answers[0] as any).data);
|
console.log('Second query NS:', (response2.answers![0] as any).data);
|
||||||
|
|
||||||
// This pattern rotates between records but returns one at a time per query
|
// This pattern rotates between records but returns one at a time per query
|
||||||
expect(response1.answers.length).toEqual(1);
|
expect(response1.answers!.length).toEqual(1);
|
||||||
expect(response2.answers.length).toEqual(1);
|
expect(response2.answers!.length).toEqual(1);
|
||||||
expect((response1.answers[0] as any).data).toEqual('ns1.example.com');
|
expect((response1.answers![0] as any).data).toEqual('ns1.example.com');
|
||||||
expect((response2.answers[0] as any).data).toEqual('ns2.example.com');
|
expect((response2.answers![0] as any).data).toEqual('ns2.example.com');
|
||||||
|
|
||||||
await stopServer(dnsServer);
|
await stopServer(dnsServer);
|
||||||
dnsServer = null;
|
dnsServer = null;
|
||||||
|
|||||||
+26
-18
@@ -1,6 +1,6 @@
|
|||||||
import * as plugins from '../ts_server/plugins.js';
|
import * as plugins from '../ts_server/plugins.js';
|
||||||
import { expect, tap } from '@git.zone/tstest/tapbundle';
|
import { expect, tap } from '@git.zone/tstest/tapbundle';
|
||||||
import { tapNodeTools } from '@git.zone/tstest/tapbundle_serverside';
|
import { TapNodeTools } from '@git.zone/tstest/tapbundle_serverside';
|
||||||
import { execSync } from 'child_process';
|
import { execSync } from 'child_process';
|
||||||
|
|
||||||
import * as dnsPacket from 'dns-packet';
|
import * as dnsPacket from 'dns-packet';
|
||||||
@@ -12,6 +12,8 @@ import * as os from 'os';
|
|||||||
|
|
||||||
import * as smartdns from '../ts_server/index.js';
|
import * as smartdns from '../ts_server/index.js';
|
||||||
|
|
||||||
|
const tapNodeTools = new TapNodeTools(tap);
|
||||||
|
|
||||||
// Generate a real self-signed certificate using OpenSSL
|
// Generate a real self-signed certificate using OpenSSL
|
||||||
function generateSelfSignedCert() {
|
function generateSelfSignedCert() {
|
||||||
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cert-'));
|
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cert-'));
|
||||||
@@ -48,7 +50,7 @@ function generateSelfSignedCert() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Cache the generated certificate for performance
|
// Cache the generated certificate for performance
|
||||||
let cachedCert = null;
|
let cachedCert: { key: string; cert: string } | null = null;
|
||||||
|
|
||||||
// Helper function to get certificate
|
// Helper function to get certificate
|
||||||
function getTestCertificate() {
|
function getTestCertificate() {
|
||||||
@@ -108,7 +110,7 @@ const acmeClientMock = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
forge: {
|
forge: {
|
||||||
createCsr({commonName, altNames}) {
|
createCsr({ commonName, altNames }: { commonName: string; altNames: string[] }) {
|
||||||
return Promise.resolve({
|
return Promise.resolve({
|
||||||
csr: Buffer.from('mock-csr-data')
|
csr: Buffer.from('mock-csr-data')
|
||||||
});
|
});
|
||||||
@@ -125,7 +127,7 @@ const acmeClientMock = {
|
|||||||
|
|
||||||
// Override generateKeyPairSync to use our test key for certificate generation in tests
|
// Override generateKeyPairSync to use our test key for certificate generation in tests
|
||||||
const originalGenerateKeyPairSync = plugins.crypto.generateKeyPairSync;
|
const originalGenerateKeyPairSync = plugins.crypto.generateKeyPairSync;
|
||||||
plugins.crypto.generateKeyPairSync = function(type, options) {
|
(plugins.crypto.generateKeyPairSync as any) = function(this: any, type: string, options?: any) {
|
||||||
if (type === 'rsa' &&
|
if (type === 'rsa' &&
|
||||||
options?.modulusLength === 2048 &&
|
options?.modulusLength === 2048 &&
|
||||||
options?.privateKeyEncoding?.type === 'pkcs8') {
|
options?.privateKeyEncoding?.type === 'pkcs8') {
|
||||||
@@ -143,10 +145,10 @@ plugins.crypto.generateKeyPairSync = function(type, options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Use the original function for other cases
|
// Use the original function for other cases
|
||||||
return originalGenerateKeyPairSync.apply(this, arguments);
|
return (originalGenerateKeyPairSync as any).apply(this, arguments);
|
||||||
};
|
};
|
||||||
|
|
||||||
let dnsServer: smartdns.DnsServer;
|
let dnsServer: smartdns.DnsServer | null;
|
||||||
const testCertDir = path.join(process.cwd(), 'test-certs');
|
const testCertDir = path.join(process.cwd(), 'test-certs');
|
||||||
|
|
||||||
// Helper to clean up test certificate directory
|
// Helper to clean up test certificate directory
|
||||||
@@ -187,7 +189,7 @@ async function stopServer(server: smartdns.DnsServer | null | undefined) {
|
|||||||
|
|
||||||
await Promise.race([stopPromise, timeoutPromise]);
|
await Promise.race([stopPromise, timeoutPromise]);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log('Handled error when stopping server:', e.message || e);
|
console.log('Handled error when stopping server:', e instanceof Error ? e.message : e);
|
||||||
|
|
||||||
// Force close if normal stop fails
|
// Force close if normal stop fails
|
||||||
try {
|
try {
|
||||||
@@ -202,7 +204,7 @@ async function stopServer(server: smartdns.DnsServer | null | undefined) {
|
|||||||
(server as any).udpServer = null;
|
(server as any).udpServer = null;
|
||||||
}
|
}
|
||||||
} catch (forceError) {
|
} catch (forceError) {
|
||||||
console.log('Force cleanup error:', forceError.message || forceError);
|
console.log('Force cleanup error:', forceError instanceof Error ? forceError.message : forceError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -400,7 +402,7 @@ tap.test('lets query over https', async () => {
|
|||||||
|
|
||||||
const response = await fetch(`https://localhost:${httpsPort}/dns-query`, {
|
const response = await fetch(`https://localhost:${httpsPort}/dns-query`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: query,
|
body: query as unknown as BodyInit,
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/dns-message',
|
'Content-Type': 'application/dns-message',
|
||||||
}
|
}
|
||||||
@@ -411,9 +413,9 @@ tap.test('lets query over https', async () => {
|
|||||||
const responseData = await response.arrayBuffer();
|
const responseData = await response.arrayBuffer();
|
||||||
const dnsResponse = dnsPacket.decode(Buffer.from(responseData));
|
const dnsResponse = dnsPacket.decode(Buffer.from(responseData));
|
||||||
|
|
||||||
console.log(dnsResponse.answers[0]);
|
console.log(dnsResponse.answers![0]);
|
||||||
|
|
||||||
expect(dnsResponse.answers[0]).toEqual({
|
expect(dnsResponse.answers![0]).toEqual({
|
||||||
name: 'dnsly_a.bleu.de',
|
name: 'dnsly_a.bleu.de',
|
||||||
type: 'A',
|
type: 'A',
|
||||||
class: 'IN',
|
class: 'IN',
|
||||||
@@ -494,9 +496,9 @@ tap.test('lets query over udp', async () => {
|
|||||||
|
|
||||||
const dnsResponse = await responsePromise;
|
const dnsResponse = await responsePromise;
|
||||||
|
|
||||||
console.log(dnsResponse.answers[0]);
|
console.log(dnsResponse.answers![0]);
|
||||||
|
|
||||||
expect(dnsResponse.answers[0]).toEqual({
|
expect(dnsResponse.answers![0]).toEqual({
|
||||||
name: 'dnsly_a.bleu.de',
|
name: 'dnsly_a.bleu.de',
|
||||||
type: 'A',
|
type: 'A',
|
||||||
class: 'IN',
|
class: 'IN',
|
||||||
@@ -674,14 +676,17 @@ tap.test('should reject invalid IP addresses', async () => {
|
|||||||
udpBindInterface: 'invalid-ip',
|
udpBindInterface: 'invalid-ip',
|
||||||
});
|
});
|
||||||
|
|
||||||
let error1 = null;
|
let error1: Error | null = null;
|
||||||
try {
|
try {
|
||||||
await dnsServer.start();
|
await dnsServer.start();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
error1 = err;
|
error1 = err instanceof Error ? err : new Error(String(err));
|
||||||
}
|
}
|
||||||
|
|
||||||
expect(error1).toBeDefined();
|
expect(error1).toBeDefined();
|
||||||
|
if (!error1) {
|
||||||
|
throw new Error('Expected invalid UDP bind interface to throw');
|
||||||
|
}
|
||||||
expect(error1.message).toContain('Invalid UDP bind interface');
|
expect(error1.message).toContain('Invalid UDP bind interface');
|
||||||
|
|
||||||
// Test invalid HTTPS interface
|
// Test invalid HTTPS interface
|
||||||
@@ -694,14 +699,17 @@ tap.test('should reject invalid IP addresses', async () => {
|
|||||||
httpsBindInterface: '999.999.999.999',
|
httpsBindInterface: '999.999.999.999',
|
||||||
});
|
});
|
||||||
|
|
||||||
let error2 = null;
|
let error2: Error | null = null;
|
||||||
try {
|
try {
|
||||||
await dnsServer.start();
|
await dnsServer.start();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
error2 = err;
|
error2 = err instanceof Error ? err : new Error(String(err));
|
||||||
}
|
}
|
||||||
|
|
||||||
expect(error2).toBeDefined();
|
expect(error2).toBeDefined();
|
||||||
|
if (!error2) {
|
||||||
|
throw new Error('Expected invalid HTTPS bind interface to throw');
|
||||||
|
}
|
||||||
expect(error2.message).toContain('Invalid HTTPS bind interface');
|
expect(error2.message).toContain('Invalid HTTPS bind interface');
|
||||||
|
|
||||||
dnsServer = null;
|
dnsServer = null;
|
||||||
@@ -740,7 +748,7 @@ tap.test('should work with IPv6 localhost if available', async () => {
|
|||||||
|
|
||||||
await stopServer(dnsServer);
|
await stopServer(dnsServer);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log('IPv6 binding failed:', err.message);
|
console.log('IPv6 binding failed:', err instanceof Error ? err.message : err);
|
||||||
await stopServer(dnsServer);
|
await stopServer(dnsServer);
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-12
@@ -1,12 +1,14 @@
|
|||||||
import * as plugins from '../ts_server/plugins.js';
|
import * as plugins from '../ts_server/plugins.js';
|
||||||
import { expect, tap } from '@git.zone/tstest/tapbundle';
|
import { expect, tap } from '@git.zone/tstest/tapbundle';
|
||||||
import { tapNodeTools } from '@git.zone/tstest/tapbundle_serverside';
|
import { TapNodeTools } from '@git.zone/tstest/tapbundle_serverside';
|
||||||
import * as dnsPacket from 'dns-packet';
|
import * as dnsPacket from 'dns-packet';
|
||||||
import * as dgram from 'dgram';
|
import * as dgram from 'dgram';
|
||||||
|
|
||||||
import * as smartdns from '../ts_server/index.js';
|
import * as smartdns from '../ts_server/index.js';
|
||||||
|
|
||||||
let dnsServer: smartdns.DnsServer;
|
const tapNodeTools = new TapNodeTools(tap);
|
||||||
|
|
||||||
|
let dnsServer: smartdns.DnsServer | null;
|
||||||
|
|
||||||
// Port management for tests
|
// Port management for tests
|
||||||
let nextHttpsPort = 8700;
|
let nextHttpsPort = 8700;
|
||||||
@@ -29,7 +31,7 @@ async function stopServer(server: smartdns.DnsServer | null | undefined) {
|
|||||||
try {
|
try {
|
||||||
await server.stop();
|
await server.stop();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log('Handled error when stopping server:', e.message || e);
|
console.log('Handled error when stopping server:', e instanceof Error ? e.message : e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,7 +98,7 @@ tap.test('Direct SOA query should work without timeout', async () => {
|
|||||||
const dnsResponse = dnsPacket.decode(msg);
|
const dnsResponse = dnsPacket.decode(msg);
|
||||||
resolve(dnsResponse);
|
resolve(dnsResponse);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
reject(new Error(`Failed to decode response: ${e.message}`));
|
reject(new Error(`Failed to decode response: ${e instanceof Error ? e.message : String(e)}`));
|
||||||
}
|
}
|
||||||
client.close();
|
client.close();
|
||||||
});
|
});
|
||||||
@@ -118,9 +120,9 @@ tap.test('Direct SOA query should work without timeout', async () => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const dnsResponse = await responsePromise;
|
const dnsResponse = await responsePromise;
|
||||||
console.log('SOA response received:', dnsResponse.answers.length, 'answers');
|
console.log('SOA response received:', dnsResponse.answers!.length, 'answers');
|
||||||
|
|
||||||
const soaAnswers = dnsResponse.answers.filter(a => a.type === 'SOA');
|
const soaAnswers = dnsResponse.answers!.filter(a => a.type === 'SOA');
|
||||||
expect(soaAnswers.length).toEqual(1);
|
expect(soaAnswers.length).toEqual(1);
|
||||||
|
|
||||||
const soaData = (soaAnswers[0] as any).data;
|
const soaData = (soaAnswers[0] as any).data;
|
||||||
@@ -189,7 +191,7 @@ tap.test('SOA query with DNSSEC should work', async () => {
|
|||||||
const dnsResponse = dnsPacket.decode(msg);
|
const dnsResponse = dnsPacket.decode(msg);
|
||||||
resolve(dnsResponse);
|
resolve(dnsResponse);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
reject(new Error(`Failed to decode response: ${e.message}`));
|
reject(new Error(`Failed to decode response: ${e instanceof Error ? e.message : String(e)}`));
|
||||||
}
|
}
|
||||||
client.close();
|
client.close();
|
||||||
});
|
});
|
||||||
@@ -211,10 +213,10 @@ tap.test('SOA query with DNSSEC should work', async () => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const dnsResponse = await responsePromise;
|
const dnsResponse = await responsePromise;
|
||||||
console.log('Response received with', dnsResponse.answers.length, 'answers');
|
console.log('Response received with', dnsResponse.answers!.length, 'answers');
|
||||||
|
|
||||||
const soaAnswers = dnsResponse.answers.filter(a => a.type === 'SOA');
|
const soaAnswers = dnsResponse.answers!.filter(a => a.type === 'SOA');
|
||||||
const rrsigAnswers = dnsResponse.answers.filter(a => a.type === 'RRSIG');
|
const rrsigAnswers = dnsResponse.answers!.filter(a => a.type === 'RRSIG');
|
||||||
console.log('SOA records found:', soaAnswers.length);
|
console.log('SOA records found:', soaAnswers.length);
|
||||||
console.log('RRSIG records found:', rrsigAnswers.length);
|
console.log('RRSIG records found:', rrsigAnswers.length);
|
||||||
|
|
||||||
@@ -312,7 +314,7 @@ tap.test('SOA serialization produces correct wire format', async () => {
|
|||||||
const dnsResponse = dnsPacket.decode(msg);
|
const dnsResponse = dnsPacket.decode(msg);
|
||||||
resolve(dnsResponse);
|
resolve(dnsResponse);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
reject(new Error(`Failed to decode response: ${e.message}`));
|
reject(new Error(`Failed to decode response: ${e instanceof Error ? e.message : String(e)}`));
|
||||||
}
|
}
|
||||||
client.close();
|
client.close();
|
||||||
});
|
});
|
||||||
@@ -334,7 +336,7 @@ tap.test('SOA serialization produces correct wire format', async () => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const dnsResponse = await responsePromise;
|
const dnsResponse = await responsePromise;
|
||||||
const soaAnswers = dnsResponse.answers.filter(a => a.type === 'SOA');
|
const soaAnswers = dnsResponse.answers!.filter(a => a.type === 'SOA');
|
||||||
expect(soaAnswers.length).toEqual(1);
|
expect(soaAnswers.length).toEqual(1);
|
||||||
|
|
||||||
const soaData = (soaAnswers[0] as any).data;
|
const soaData = (soaAnswers[0] as any).data;
|
||||||
|
|||||||
+16
-14
@@ -1,12 +1,14 @@
|
|||||||
import * as plugins from '../ts_server/plugins.js';
|
import * as plugins from '../ts_server/plugins.js';
|
||||||
import { expect, tap } from '@git.zone/tstest/tapbundle';
|
import { expect, tap } from '@git.zone/tstest/tapbundle';
|
||||||
import { tapNodeTools } from '@git.zone/tstest/tapbundle_serverside';
|
import { TapNodeTools } from '@git.zone/tstest/tapbundle_serverside';
|
||||||
import * as dnsPacket from 'dns-packet';
|
import * as dnsPacket from 'dns-packet';
|
||||||
import * as dgram from 'dgram';
|
import * as dgram from 'dgram';
|
||||||
|
|
||||||
import * as smartdns from '../ts_server/index.js';
|
import * as smartdns from '../ts_server/index.js';
|
||||||
|
|
||||||
let dnsServer: smartdns.DnsServer;
|
const tapNodeTools = new TapNodeTools(tap);
|
||||||
|
|
||||||
|
let dnsServer: smartdns.DnsServer | null;
|
||||||
|
|
||||||
// Port management for tests
|
// Port management for tests
|
||||||
let nextHttpsPort = 8900;
|
let nextHttpsPort = 8900;
|
||||||
@@ -29,7 +31,7 @@ async function stopServer(server: smartdns.DnsServer | null | undefined) {
|
|||||||
try {
|
try {
|
||||||
await server.stop();
|
await server.stop();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log('Handled error when stopping server:', e.message || e);
|
console.log('Handled error when stopping server:', e instanceof Error ? e.message : e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,9 +120,9 @@ tap.test('SOA records work for all scenarios', async () => {
|
|||||||
client.send(soaQuery, udpPort, 'localhost');
|
client.send(soaQuery, udpPort, 'localhost');
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log('Direct SOA query response:', response.answers.length, 'answers');
|
console.log('Direct SOA query response:', response.answers!.length, 'answers');
|
||||||
expect(response.answers.length).toEqual(1);
|
expect(response.answers!.length).toEqual(1);
|
||||||
expect(response.answers[0].type).toEqual('SOA');
|
expect(response.answers![0].type).toEqual('SOA');
|
||||||
|
|
||||||
// Test 2: Non-existent domain query (should get SOA in authority)
|
// Test 2: Non-existent domain query (should get SOA in authority)
|
||||||
console.log('\n--- Test 2: Non-existent domain query ---');
|
console.log('\n--- Test 2: Non-existent domain query ---');
|
||||||
@@ -153,8 +155,8 @@ tap.test('SOA records work for all scenarios', async () => {
|
|||||||
client.send(nxQuery, udpPort, 'localhost');
|
client.send(nxQuery, udpPort, 'localhost');
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log('Non-existent query response:', response.answers.length, 'answers');
|
console.log('Non-existent query response:', response.answers!.length, 'answers');
|
||||||
const soaAnswers = response.answers.filter(a => a.type === 'SOA');
|
const soaAnswers = response.answers!.filter(a => a.type === 'SOA');
|
||||||
expect(soaAnswers.length).toEqual(1);
|
expect(soaAnswers.length).toEqual(1);
|
||||||
|
|
||||||
// Test 3: SOA with DNSSEC
|
// Test 3: SOA with DNSSEC
|
||||||
@@ -197,11 +199,11 @@ tap.test('SOA records work for all scenarios', async () => {
|
|||||||
client.send(dnssecQuery, udpPort, 'localhost');
|
client.send(dnssecQuery, udpPort, 'localhost');
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log('DNSSEC SOA query response:', response.answers.length, 'answers');
|
console.log('DNSSEC SOA query response:', response.answers!.length, 'answers');
|
||||||
console.log('Answer types:', response.answers.map(a => a.type));
|
console.log('Answer types:', response.answers!.map(a => a.type));
|
||||||
expect(response.answers.length).toEqual(2); // SOA + RRSIG
|
expect(response.answers!.length).toEqual(2); // SOA + RRSIG
|
||||||
expect(response.answers.some(a => a.type === 'SOA')).toEqual(true);
|
expect(response.answers!.some(a => a.type === 'SOA')).toEqual(true);
|
||||||
expect(response.answers.some(a => a.type === 'RRSIG')).toEqual(true);
|
expect(response.answers!.some(a => a.type === 'RRSIG')).toEqual(true);
|
||||||
|
|
||||||
client.close();
|
client.close();
|
||||||
await stopServer(dnsServer);
|
await stopServer(dnsServer);
|
||||||
@@ -259,7 +261,7 @@ tap.test('Configurable primary nameserver works correctly', async () => {
|
|||||||
client.send(query, udpPort, 'localhost');
|
client.send(query, udpPort, 'localhost');
|
||||||
});
|
});
|
||||||
|
|
||||||
const soaAnswers = response.answers.filter(a => a.type === 'SOA');
|
const soaAnswers = response.answers!.filter(a => a.type === 'SOA');
|
||||||
console.log('✅ Configured primary nameserver:', (soaAnswers[0] as any).data.mname);
|
console.log('✅ Configured primary nameserver:', (soaAnswers[0] as any).data.mname);
|
||||||
expect((soaAnswers[0] as any).data.mname).toEqual('master.test.com');
|
expect((soaAnswers[0] as any).data.mname).toEqual('master.test.com');
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
import * as plugins from '../ts_server/plugins.js';
|
import * as plugins from '../ts_server/plugins.js';
|
||||||
import { expect, tap } from '@git.zone/tstest/tapbundle';
|
import { expect, tap } from '@git.zone/tstest/tapbundle';
|
||||||
import { tapNodeTools } from '@git.zone/tstest/tapbundle_serverside';
|
import { TapNodeTools } from '@git.zone/tstest/tapbundle_serverside';
|
||||||
import * as dnsPacket from 'dns-packet';
|
import * as dnsPacket from 'dns-packet';
|
||||||
import * as dgram from 'dgram';
|
import * as dgram from 'dgram';
|
||||||
|
|
||||||
import * as smartdns from '../ts_server/index.js';
|
import * as smartdns from '../ts_server/index.js';
|
||||||
|
|
||||||
let dnsServer: smartdns.DnsServer;
|
const tapNodeTools = new TapNodeTools(tap);
|
||||||
|
|
||||||
|
let dnsServer: smartdns.DnsServer | null;
|
||||||
|
|
||||||
// Port management for tests
|
// Port management for tests
|
||||||
let nextHttpsPort = 8800;
|
let nextHttpsPort = 8800;
|
||||||
@@ -29,7 +31,7 @@ async function stopServer(server: smartdns.DnsServer | null | undefined) {
|
|||||||
try {
|
try {
|
||||||
await server.stop();
|
await server.stop();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log('Handled error when stopping server:', e.message || e);
|
console.log('Handled error when stopping server:', e instanceof Error ? e.message : e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,7 +100,7 @@ tap.test('Simple SOA query without DNSSEC', async () => {
|
|||||||
const dnsResponse = await responsePromise;
|
const dnsResponse = await responsePromise;
|
||||||
console.log('✅ SOA response without DNSSEC received');
|
console.log('✅ SOA response without DNSSEC received');
|
||||||
|
|
||||||
const soaAnswers = dnsResponse.answers.filter(a => a.type === 'SOA');
|
const soaAnswers = dnsResponse.answers!.filter(a => a.type === 'SOA');
|
||||||
expect(soaAnswers.length).toEqual(1);
|
expect(soaAnswers.length).toEqual(1);
|
||||||
|
|
||||||
const soaData = (soaAnswers[0] as any).data;
|
const soaData = (soaAnswers[0] as any).data;
|
||||||
@@ -191,7 +193,7 @@ tap.test('Direct SOA query without DNSSEC', async () => {
|
|||||||
const dnsResponse = await responsePromise;
|
const dnsResponse = await responsePromise;
|
||||||
console.log('✅ Direct SOA query succeeded');
|
console.log('✅ Direct SOA query succeeded');
|
||||||
|
|
||||||
const soaAnswers = dnsResponse.answers.filter(a => a.type === 'SOA');
|
const soaAnswers = dnsResponse.answers!.filter(a => a.type === 'SOA');
|
||||||
expect(soaAnswers.length).toEqual(1);
|
expect(soaAnswers.length).toEqual(1);
|
||||||
|
|
||||||
await stopServer(dnsServer);
|
await stopServer(dnsServer);
|
||||||
|
|||||||
+13
-11
@@ -1,11 +1,13 @@
|
|||||||
import { expect, tap } from '@git.zone/tstest/tapbundle';
|
import { expect, tap } from '@git.zone/tstest/tapbundle';
|
||||||
import { tapNodeTools } from '@git.zone/tstest/tapbundle_serverside';
|
import { TapNodeTools } from '@git.zone/tstest/tapbundle_serverside';
|
||||||
import * as dnsPacket from 'dns-packet';
|
import * as dnsPacket from 'dns-packet';
|
||||||
import * as dgram from 'dgram';
|
import * as dgram from 'dgram';
|
||||||
|
|
||||||
import * as smartdns from '../ts_server/index.js';
|
import * as smartdns from '../ts_server/index.js';
|
||||||
|
|
||||||
let dnsServer: smartdns.DnsServer;
|
const tapNodeTools = new TapNodeTools(tap);
|
||||||
|
|
||||||
|
let dnsServer: smartdns.DnsServer | null;
|
||||||
|
|
||||||
// Cleanup function for servers
|
// Cleanup function for servers
|
||||||
async function stopServer(server: smartdns.DnsServer | null | undefined) {
|
async function stopServer(server: smartdns.DnsServer | null | undefined) {
|
||||||
@@ -16,7 +18,7 @@ async function stopServer(server: smartdns.DnsServer | null | undefined) {
|
|||||||
try {
|
try {
|
||||||
await server.stop();
|
await server.stop();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log('Handled error when stopping server:', e.message || e);
|
console.log('Handled error when stopping server:', e instanceof Error ? e.message : e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,7 +80,7 @@ tap.test('Test SOA with DNSSEC timing', async () => {
|
|||||||
const dnsResponse = dnsPacket.decode(msg);
|
const dnsResponse = dnsPacket.decode(msg);
|
||||||
resolve(dnsResponse);
|
resolve(dnsResponse);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
reject(new Error(`Failed to decode response: ${e.message}`));
|
reject(new Error(`Failed to decode response: ${e instanceof Error ? e.message : String(e)}`));
|
||||||
}
|
}
|
||||||
client.close();
|
client.close();
|
||||||
});
|
});
|
||||||
@@ -103,11 +105,11 @@ tap.test('Test SOA with DNSSEC timing', async () => {
|
|||||||
try {
|
try {
|
||||||
const dnsResponse = await responsePromise;
|
const dnsResponse = await responsePromise;
|
||||||
console.log('Response details:');
|
console.log('Response details:');
|
||||||
console.log('- Answers:', dnsResponse.answers.length);
|
console.log('- Answers:', dnsResponse.answers!.length);
|
||||||
console.log('- Answer types:', dnsResponse.answers.map(a => a.type));
|
console.log('- Answer types:', dnsResponse.answers!.map(a => a.type));
|
||||||
|
|
||||||
const soaAnswers = dnsResponse.answers.filter(a => a.type === 'SOA');
|
const soaAnswers = dnsResponse.answers!.filter(a => a.type === 'SOA');
|
||||||
const rrsigAnswers = dnsResponse.answers.filter(a => a.type === 'RRSIG');
|
const rrsigAnswers = dnsResponse.answers!.filter(a => a.type === 'RRSIG');
|
||||||
|
|
||||||
console.log('- SOA records:', soaAnswers.length);
|
console.log('- SOA records:', soaAnswers.length);
|
||||||
console.log('- RRSIG records:', rrsigAnswers.length);
|
console.log('- RRSIG records:', rrsigAnswers.length);
|
||||||
@@ -187,7 +189,7 @@ tap.test('DNSSEC signing completes within reasonable time', async () => {
|
|||||||
const dnsResponse = dnsPacket.decode(msg);
|
const dnsResponse = dnsPacket.decode(msg);
|
||||||
resolve(dnsResponse);
|
resolve(dnsResponse);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
reject(new Error(`Failed to decode response: ${e.message}`));
|
reject(new Error(`Failed to decode response: ${e instanceof Error ? e.message : String(e)}`));
|
||||||
}
|
}
|
||||||
client.close();
|
client.close();
|
||||||
});
|
});
|
||||||
@@ -215,8 +217,8 @@ tap.test('DNSSEC signing completes within reasonable time', async () => {
|
|||||||
expect(elapsed).toBeLessThan(2000);
|
expect(elapsed).toBeLessThan(2000);
|
||||||
|
|
||||||
// Verify correctness: SOA + RRSIG present
|
// Verify correctness: SOA + RRSIG present
|
||||||
const soaAnswers = dnsResponse.answers.filter(a => a.type === 'SOA');
|
const soaAnswers = dnsResponse.answers!.filter(a => a.type === 'SOA');
|
||||||
const rrsigAnswers = dnsResponse.answers.filter(a => a.type === 'RRSIG');
|
const rrsigAnswers = dnsResponse.answers!.filter(a => a.type === 'RRSIG');
|
||||||
|
|
||||||
expect(soaAnswers.length).toEqual(1);
|
expect(soaAnswers.length).toEqual(1);
|
||||||
expect(rrsigAnswers.length).toBeGreaterThan(0);
|
expect(rrsigAnswers.length).toBeGreaterThan(0);
|
||||||
|
|||||||
@@ -3,6 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@push.rocks/smartdns',
|
name: '@push.rocks/smartdns',
|
||||||
version: '7.9.0',
|
version: '7.9.1',
|
||||||
description: 'A robust TypeScript library providing advanced DNS management and resolution capabilities including support for DNSSEC, custom DNS servers, and integration with various DNS providers.'
|
description: 'A robust TypeScript library providing advanced DNS management and resolution capabilities including support for DNSSEC, custom DNS servers, and integration with various DNS providers.'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -248,10 +248,11 @@ export class Smartdns {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const returnArray: plugins.tsclass.network.IDnsRecord[] = [];
|
const returnArray: plugins.tsclass.network.IDnsRecord[] = [];
|
||||||
for (const recordKey in recordsArg) {
|
for (const record of recordsArg as unknown[]) {
|
||||||
|
const value = Array.isArray(record) ? record.join('') : String(record);
|
||||||
returnArray.push({
|
returnArray.push({
|
||||||
name: recordNameArg,
|
name: recordNameArg,
|
||||||
value: recordsArg[recordKey][0],
|
value,
|
||||||
type: recordTypeArg,
|
type: recordTypeArg,
|
||||||
dnsSecEnabled: false,
|
dnsSecEnabled: false,
|
||||||
});
|
});
|
||||||
@@ -280,7 +281,7 @@ export class Smartdns {
|
|||||||
|
|
||||||
public convertDnsTypeNumberToTypeName(
|
public convertDnsTypeNumberToTypeName(
|
||||||
dnsTypeNumberArg: number
|
dnsTypeNumberArg: number
|
||||||
): plugins.tsclass.network.TDnsRecordType {
|
): plugins.tsclass.network.TDnsRecordType | null {
|
||||||
for (const key in this.dnsTypeMap) {
|
for (const key in this.dnsTypeMap) {
|
||||||
if (this.dnsTypeMap[key] === dnsTypeNumberArg) {
|
if (this.dnsTypeMap[key] === dnsTypeNumberArg) {
|
||||||
return key as plugins.tsclass.network.TDnsRecordType;
|
return key as plugins.tsclass.network.TDnsRecordType;
|
||||||
|
|||||||
+3
-1
@@ -5,8 +5,10 @@
|
|||||||
"target": "ES2022",
|
"target": "ES2022",
|
||||||
"module": "NodeNext",
|
"module": "NodeNext",
|
||||||
"moduleResolution": "NodeNext",
|
"moduleResolution": "NodeNext",
|
||||||
|
"noImplicitAny": true,
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"verbatimModuleSyntax": true
|
"verbatimModuleSyntax": true,
|
||||||
|
"types": ["node"]
|
||||||
},
|
},
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"dist_*/**/*.d.ts"
|
"dist_*/**/*.d.ts"
|
||||||
|
|||||||
Reference in New Issue
Block a user