Compare commits
65 Commits
Author | SHA1 | Date | |
---|---|---|---|
5278c2ce78 | |||
439d08b023 | |||
1536475306 | |||
5c06ae1edb | |||
2cfecab96f | |||
7eb8a46c7c | |||
c56e732d6d | |||
aff5f2e7d9 | |||
6c38ff36d7 | |||
b45cda5084 | |||
dedd3a3f82 | |||
f2dffb6e88 | |||
2a1fbeb183 | |||
a6a47d2e96 | |||
84ad6bbcd6 | |||
4102c3a692 | |||
6281ab0c80 | |||
622c65291e | |||
dd8c97b99a | |||
9c56dc51e3 | |||
45cbd3a953 | |||
d3e2655212 | |||
e02b2253f5 | |||
862577745d | |||
ca72206ab4 | |||
0221c3207e | |||
f2b8fa57af | |||
e5b072d99b | |||
97c57b2865 | |||
e04485231d | |||
228bc88d60 | |||
811041b036 | |||
a1203366d7 | |||
0deb77cda8 | |||
ed8b7ec65a | |||
6cfc12f83f | |||
efd9bbb77a | |||
b463aea274 | |||
c8cf590a5a | |||
42f679ef61 | |||
0cb882bb7d | |||
66f817cdf8 | |||
5925c882c8 | |||
6f09a82eee | |||
e23579709a | |||
929e4152d3 | |||
d0527affc2 | |||
f2ebaf74d9 | |||
b6d8c36f3e | |||
587600d571 | |||
17f293ca4e | |||
0ed946ee63 | |||
e720d5905e | |||
6286bfaa8f | |||
9390bbae61 | |||
ebb007bcdb | |||
e6d99d5664 | |||
7b29efc398 | |||
64c381d42f | |||
d4dbf4f2b3 | |||
562dca35a7 | |||
2bbbbc17e8 | |||
4ada87a945 | |||
3e45a24750 | |||
96b4926f8f |
22
.gitignore
vendored
22
.gitignore
vendored
@ -1,4 +1,20 @@
|
|||||||
node_modules/
|
.nogit/
|
||||||
pages/
|
|
||||||
public/
|
# artifacts
|
||||||
coverage/
|
coverage/
|
||||||
|
public/
|
||||||
|
pages/
|
||||||
|
|
||||||
|
# installs
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# caches
|
||||||
|
.yarn/
|
||||||
|
.cache/
|
||||||
|
.rpt2_cache
|
||||||
|
|
||||||
|
# builds
|
||||||
|
dist/
|
||||||
|
dist_*/
|
||||||
|
|
||||||
|
# custom
|
@ -1,72 +0,0 @@
|
|||||||
# gitzone standard
|
|
||||||
image: hosttoday/ht-docker-node:npmci
|
|
||||||
|
|
||||||
cache:
|
|
||||||
paths:
|
|
||||||
- .yarn/
|
|
||||||
key: "$CI_BUILD_STAGE"
|
|
||||||
|
|
||||||
stages:
|
|
||||||
- test
|
|
||||||
- release
|
|
||||||
- trigger
|
|
||||||
- pages
|
|
||||||
|
|
||||||
testLEGACY:
|
|
||||||
stage: test
|
|
||||||
script:
|
|
||||||
- npmci test legacy
|
|
||||||
coverage: /\d+.?\d+?\%\s*coverage/
|
|
||||||
tags:
|
|
||||||
- docker
|
|
||||||
allow_failure: true
|
|
||||||
|
|
||||||
testLTS:
|
|
||||||
stage: test
|
|
||||||
script:
|
|
||||||
- npmci test lts
|
|
||||||
coverage: /\d+.?\d+?\%\s*coverage/
|
|
||||||
tags:
|
|
||||||
- docker
|
|
||||||
|
|
||||||
testSTABLE:
|
|
||||||
stage: test
|
|
||||||
script:
|
|
||||||
- npmci test stable
|
|
||||||
coverage: /\d+.?\d+?\%\s*coverage/
|
|
||||||
tags:
|
|
||||||
- docker
|
|
||||||
|
|
||||||
release:
|
|
||||||
stage: release
|
|
||||||
script:
|
|
||||||
- npmci publish
|
|
||||||
only:
|
|
||||||
- tags
|
|
||||||
tags:
|
|
||||||
- docker
|
|
||||||
|
|
||||||
trigger:
|
|
||||||
stage: trigger
|
|
||||||
script:
|
|
||||||
- npmci trigger
|
|
||||||
only:
|
|
||||||
- tags
|
|
||||||
tags:
|
|
||||||
- docker
|
|
||||||
|
|
||||||
pages:
|
|
||||||
image: hosttoday/ht-docker-node:npmci
|
|
||||||
stage: pages
|
|
||||||
script:
|
|
||||||
- npmci command yarn global add npmpage
|
|
||||||
- npmci command npmpage
|
|
||||||
tags:
|
|
||||||
- docker
|
|
||||||
only:
|
|
||||||
- tags
|
|
||||||
artifacts:
|
|
||||||
expire_in: 1 week
|
|
||||||
paths:
|
|
||||||
- public
|
|
||||||
allow_failure: true
|
|
11
.vscode/launch.json
vendored
Normal file
11
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"command": "npm test",
|
||||||
|
"name": "Run npm test",
|
||||||
|
"request": "launch",
|
||||||
|
"type": "node-terminal"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
26
.vscode/settings.json
vendored
Normal file
26
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"json.schemas": [
|
||||||
|
{
|
||||||
|
"fileMatch": ["/npmextra.json"],
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"npmci": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "settings for npmci"
|
||||||
|
},
|
||||||
|
"gitzone": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "settings for gitzone",
|
||||||
|
"properties": {
|
||||||
|
"projectType": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["website", "element", "service", "npm", "wcc"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
102
changelog.md
Normal file
102
changelog.md
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
## 2024-09-19 - 6.1.1 - fix(ts_server)
|
||||||
|
Update DnsSec class to fully implement key generation and DNSKEY record creation.
|
||||||
|
|
||||||
|
- Added complete support for ECDSA and ED25519 algorithms in the DnsSec class.
|
||||||
|
- Implemented DNSKEY generation and KeyTag computation methods.
|
||||||
|
- Improved error handling and initialized the appropriate cryptographic instances based on the algorithm.
|
||||||
|
|
||||||
|
## 2024-09-18 - 6.1.0 - feat(smartdns)
|
||||||
|
Add DNS Server and DNSSEC tools with comprehensive unit tests
|
||||||
|
|
||||||
|
- Updated package dependencies to the latest versions
|
||||||
|
- Introduced DnsServer class for handling DNS requests over both HTTPS and UDP with support for custom handlers
|
||||||
|
- Added DnsSec class for generating and managing DNSSEC keys and DS records
|
||||||
|
- Implemented unit tests for DnsServer and Smartdns classes
|
||||||
|
|
||||||
|
## 2024-06-02 - 6.0.0 - server/client
|
||||||
|
Main description here
|
||||||
|
|
||||||
|
- **Breaking Change:** Move from client only to server + client exports.
|
||||||
|
|
||||||
|
## 2024-03-30 - 5.0.4 - maintenance
|
||||||
|
Range contains relevant changes
|
||||||
|
|
||||||
|
- Switch to new org scheme
|
||||||
|
|
||||||
|
## 2023-04-08 - 5.0.4 - core
|
||||||
|
Main description here
|
||||||
|
|
||||||
|
- Core update
|
||||||
|
- Fixes applied to the system
|
||||||
|
|
||||||
|
## 2022-07-27 - 5.0.0 - core
|
||||||
|
Update contains relevant changes
|
||||||
|
|
||||||
|
- **Breaking Change:** Major update and core changes
|
||||||
|
- Fixes and updates applied
|
||||||
|
|
||||||
|
## 2022-07-27 - 4.0.11 - core
|
||||||
|
Range contains relevant changes
|
||||||
|
|
||||||
|
- **Breaking Change:** Core update and changes applied
|
||||||
|
|
||||||
|
## 2021-08-24 - 4.0.10 - core
|
||||||
|
Range contains relevant changes
|
||||||
|
|
||||||
|
- Fixes applied to the core functionalities
|
||||||
|
|
||||||
|
## 2021-01-23 - 4.0.8 - core
|
||||||
|
Range contains relevant changes
|
||||||
|
|
||||||
|
- Updates and fixes to the core components
|
||||||
|
|
||||||
|
## 2020-08-05 - 4.0.4 - core
|
||||||
|
Range contains relevant changes
|
||||||
|
|
||||||
|
- Multiple core fixes applied
|
||||||
|
|
||||||
|
## 2020-02-15 - 4.0.0 - core
|
||||||
|
Main description here
|
||||||
|
|
||||||
|
- Core updates
|
||||||
|
- Fixes applied across the system
|
||||||
|
|
||||||
|
## 2020-02-15 - 3.0.8 - core
|
||||||
|
Core updates with major changes
|
||||||
|
|
||||||
|
- **Breaking Change:** Now uses Google DNS HTTPS API and handles DNSSEC validation
|
||||||
|
|
||||||
|
## 2019-01-07 - 3.0.6 - core
|
||||||
|
Range contains relevant changes
|
||||||
|
|
||||||
|
- Fixes and updates applied to the core
|
||||||
|
|
||||||
|
## 2018-05-13 - 3.0.4 - core
|
||||||
|
Range contains relevant changes
|
||||||
|
|
||||||
|
- Fixes applied, including `fix .checkUntilAvailable` error
|
||||||
|
|
||||||
|
## 2018-05-13 - 3.0.0 - ci
|
||||||
|
Main description here
|
||||||
|
|
||||||
|
- CI changes and updates to the access level and global packages
|
||||||
|
|
||||||
|
## 2017-07-31 - 2.0.10 - package
|
||||||
|
Update to new package name and improved record retrieval
|
||||||
|
|
||||||
|
- **Breaking Change:** Package name update and record retrieval improvements
|
||||||
|
|
||||||
|
## 2017-01-27 - 2.0.1 - maintenance
|
||||||
|
Multiple fixes and merges
|
||||||
|
|
||||||
|
## 2017-01-27 - 2.0.0 - core
|
||||||
|
Fix typings and update to better API
|
||||||
|
|
||||||
|
## 2016-11-15 - 1.0.7 - initial
|
||||||
|
Initial setup and improvements
|
||||||
|
|
||||||
|
- Initial deployment
|
||||||
|
- README improvements
|
||||||
|
|
5
dist/dnsly.plugins.d.ts
vendored
5
dist/dnsly.plugins.d.ts
vendored
@ -1,5 +0,0 @@
|
|||||||
import 'typings-global';
|
|
||||||
import * as beautylog from 'beautylog';
|
|
||||||
import * as dns from 'dns';
|
|
||||||
import * as smartdelay from 'smartdelay';
|
|
||||||
export { beautylog, dns, smartdelay };
|
|
10
dist/dnsly.plugins.js
vendored
10
dist/dnsly.plugins.js
vendored
@ -1,10 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
require("typings-global");
|
|
||||||
const beautylog = require("beautylog");
|
|
||||||
exports.beautylog = beautylog;
|
|
||||||
const dns = require("dns");
|
|
||||||
exports.dns = dns;
|
|
||||||
const smartdelay = require("smartdelay");
|
|
||||||
exports.smartdelay = smartdelay;
|
|
||||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZG5zbHkucGx1Z2lucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL2Ruc2x5LnBsdWdpbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSwwQkFBdUI7QUFDdkIsdUNBQXNDO0FBS2xDLDhCQUFTO0FBSmIsMkJBQTBCO0FBS3RCLGtCQUFHO0FBSlAseUNBQXdDO0FBS3BDLGdDQUFVIn0=
|
|
44
dist/index.d.ts
vendored
44
dist/index.d.ts
vendored
@ -1,44 +0,0 @@
|
|||||||
export declare type TDnsProvider = 'google';
|
|
||||||
export declare type TDnsRecordType = 'A' | 'AAAA' | 'CNAME' | 'PTR' | 'MX' | 'NAPTR' | 'NS' | 'SOA' | 'SRV' | 'TXT';
|
|
||||||
export interface IDnsRecord {
|
|
||||||
chunked?: string[];
|
|
||||||
name: string;
|
|
||||||
type: TDnsRecordType;
|
|
||||||
value: string;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* class dnsly offers methods for working with dns from a dns provider like Google DNS
|
|
||||||
*/
|
|
||||||
export declare class Dnsly {
|
|
||||||
dnsServerIp: string;
|
|
||||||
dnsServerPort: number;
|
|
||||||
/**
|
|
||||||
* constructor for class dnsly
|
|
||||||
*/
|
|
||||||
constructor(dnsProviderArg?: TDnsProvider);
|
|
||||||
/**
|
|
||||||
* gets a record
|
|
||||||
*/
|
|
||||||
getRecord(recordNameArg: string, recordTypeArg: TDnsRecordType): Promise<IDnsRecord[]>;
|
|
||||||
checkUntilAvailable(recordNameArg: string, recordTypeArg: TDnsRecordType, expectedValue: string): Promise<any>;
|
|
||||||
/**
|
|
||||||
* get A Dns Record
|
|
||||||
*/
|
|
||||||
getRecordA(recordNameArg: string): Promise<IDnsRecord[]>;
|
|
||||||
/**
|
|
||||||
* get AAAA Record
|
|
||||||
*/
|
|
||||||
getRecordAAAA(recordNameArg: string): Promise<IDnsRecord[]>;
|
|
||||||
/**
|
|
||||||
* gets a txt record
|
|
||||||
*/
|
|
||||||
getRecordTxt(recordNameArg: string): Promise<IDnsRecord[]>;
|
|
||||||
/**
|
|
||||||
* get oridinary record
|
|
||||||
*/
|
|
||||||
private getOrdinaryRecord(recordNameArg, recordTypeArg);
|
|
||||||
/**
|
|
||||||
* set the DNS provider
|
|
||||||
*/
|
|
||||||
private _setDnsProvider(dnsProvider);
|
|
||||||
}
|
|
145
dist/index.js
vendored
145
dist/index.js
vendored
@ -1,145 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
||||||
return new (P || (P = Promise))(function (resolve, reject) {
|
|
||||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
||||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
||||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
|
||||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
||||||
});
|
|
||||||
};
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
const q = require("smartq");
|
|
||||||
const plugins = require("./dnsly.plugins");
|
|
||||||
/**
|
|
||||||
* class dnsly offers methods for working with dns from a dns provider like Google DNS
|
|
||||||
*/
|
|
||||||
class Dnsly {
|
|
||||||
/**
|
|
||||||
* constructor for class dnsly
|
|
||||||
*/
|
|
||||||
constructor(dnsProviderArg = 'google') {
|
|
||||||
this._setDnsProvider(dnsProviderArg);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* gets a record
|
|
||||||
*/
|
|
||||||
getRecord(recordNameArg, recordTypeArg) {
|
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
|
||||||
switch (recordTypeArg) {
|
|
||||||
case 'TXT':
|
|
||||||
return yield this.getRecordTxt(recordNameArg);
|
|
||||||
case 'A':
|
|
||||||
return yield this.getRecordA(recordNameArg);
|
|
||||||
case 'AAAA':
|
|
||||||
return yield this.getRecordAAAA(recordNameArg);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
checkUntilAvailable(recordNameArg, recordTypeArg, expectedValue) {
|
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
|
||||||
let cycleArg = 0;
|
|
||||||
let doCheck = () => __awaiter(this, void 0, void 0, function* () {
|
|
||||||
if (cycleArg < 30) {
|
|
||||||
cycleArg++;
|
|
||||||
try {
|
|
||||||
let myRecordArray = yield this.getRecord(recordNameArg, recordTypeArg);
|
|
||||||
let myRecord = myRecordArray[0].value;
|
|
||||||
if (myRecord === expectedValue) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
yield plugins.smartdelay.delayFor(500);
|
|
||||||
return yield doCheck();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
yield plugins.smartdelay.delayFor(500);
|
|
||||||
return yield doCheck();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
console.log('failed permanently...');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return yield doCheck();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* get A Dns Record
|
|
||||||
*/
|
|
||||||
getRecordA(recordNameArg) {
|
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
|
||||||
return yield this.getOrdinaryRecord(recordNameArg, 'A');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* get AAAA Record
|
|
||||||
*/
|
|
||||||
getRecordAAAA(recordNameArg) {
|
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
|
||||||
return yield this.getOrdinaryRecord(recordNameArg, 'AAAA');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* gets a txt record
|
|
||||||
*/
|
|
||||||
getRecordTxt(recordNameArg) {
|
|
||||||
let done = q.defer();
|
|
||||||
plugins.dns.resolveTxt(recordNameArg, (err, recordsArg) => {
|
|
||||||
if (err) {
|
|
||||||
done.reject(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let responseArray = [];
|
|
||||||
for (let record of recordsArg) {
|
|
||||||
let recordAny = record; // fix wrong typings
|
|
||||||
responseArray.push({
|
|
||||||
chunked: recordAny,
|
|
||||||
name: recordNameArg,
|
|
||||||
value: recordAny.join(' '),
|
|
||||||
type: 'TXT'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
done.resolve(responseArray);
|
|
||||||
});
|
|
||||||
return done.promise;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* get oridinary record
|
|
||||||
*/
|
|
||||||
getOrdinaryRecord(recordNameArg, recordTypeArg) {
|
|
||||||
let done = q.defer();
|
|
||||||
plugins.dns.resolve(recordNameArg, recordTypeArg, (err, recordsArg) => {
|
|
||||||
if (err) {
|
|
||||||
done.reject(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let responseArray = [];
|
|
||||||
for (let recordKey in recordsArg) {
|
|
||||||
responseArray.push({
|
|
||||||
name: recordNameArg,
|
|
||||||
value: recordsArg[recordKey],
|
|
||||||
type: recordTypeArg
|
|
||||||
});
|
|
||||||
}
|
|
||||||
done.resolve(responseArray);
|
|
||||||
});
|
|
||||||
return done.promise;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* set the DNS provider
|
|
||||||
*/
|
|
||||||
_setDnsProvider(dnsProvider) {
|
|
||||||
if (dnsProvider === 'google') {
|
|
||||||
this.dnsServerIp = '8.8.8.8';
|
|
||||||
this.dnsServerPort = 53;
|
|
||||||
plugins.dns.setServers(['8.8.8.8', '8.8.4.4']);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new Error('unknown dns provider');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exports.Dnsly = Dnsly;
|
|
||||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7O0FBQUEsNEJBQTJCO0FBQzNCLDJDQUEwQztBQXFCMUM7O0dBRUc7QUFDSDtJQUdFOztPQUVHO0lBQ0gsWUFBWSxpQkFBK0IsUUFBUTtRQUNqRCxJQUFJLENBQUMsZUFBZSxDQUFDLGNBQWMsQ0FBQyxDQUFBO0lBQ3RDLENBQUM7SUFFRDs7T0FFRztJQUNHLFNBQVMsQ0FBRSxhQUFxQixFQUFFLGFBQTZCOztZQUNuRSxNQUFNLENBQUMsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDO2dCQUN0QixLQUFLLEtBQUs7b0JBQ1IsTUFBTSxDQUFDLE1BQU0sSUFBSSxDQUFDLFlBQVksQ0FBQyxhQUFhLENBQUMsQ0FBQTtnQkFDL0MsS0FBSyxHQUFHO29CQUNOLE1BQU0sQ0FBQyxNQUFNLElBQUksQ0FBQyxVQUFVLENBQUMsYUFBYSxDQUFDLENBQUE7Z0JBQzdDLEtBQUssTUFBTTtvQkFDVCxNQUFNLENBQUMsTUFBTSxJQUFJLENBQUMsYUFBYSxDQUFDLGFBQWEsQ0FBQyxDQUFBO1lBQ2xELENBQUM7UUFDSCxDQUFDO0tBQUE7SUFFSyxtQkFBbUIsQ0FBRSxhQUFxQixFQUFFLGFBQTZCLEVBQUUsYUFBcUI7O1lBQ3BHLElBQUksUUFBUSxHQUFHLENBQUMsQ0FBQTtZQUNoQixJQUFJLE9BQU8sR0FBRztnQkFDWixFQUFFLENBQUMsQ0FBQyxRQUFRLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQztvQkFDbEIsUUFBUSxFQUFFLENBQUE7b0JBQ1YsSUFBSSxDQUFDO3dCQUNILElBQUksYUFBYSxHQUFHLE1BQU0sSUFBSSxDQUFDLFNBQVMsQ0FBQyxhQUFhLEVBQUUsYUFBYSxDQUFDLENBQUE7d0JBQ3RFLElBQUksUUFBUSxHQUFHLGFBQWEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUE7d0JBQ3JDLEVBQUUsQ0FBQyxDQUFDLFFBQVEsS0FBSyxhQUFhLENBQUMsQ0FBQyxDQUFDOzRCQUMvQixNQUFNLENBQUMsSUFBSSxDQUFBO3dCQUNiLENBQUM7d0JBQUMsSUFBSSxDQUFDLENBQUM7NEJBQ04sTUFBTSxPQUFPLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQTs0QkFDdEMsTUFBTSxDQUFDLE1BQU0sT0FBTyxFQUFFLENBQUE7d0JBQ3hCLENBQUM7b0JBQ0gsQ0FBQztvQkFBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO3dCQUNiLE1BQU0sT0FBTyxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUE7d0JBQ3RDLE1BQU0sQ0FBQyxNQUFNLE9BQU8sRUFBRSxDQUFBO29CQUN4QixDQUFDO2dCQUNILENBQUM7Z0JBQUMsSUFBSSxDQUFDLENBQUM7b0JBQ04sT0FBTyxDQUFDLEdBQUcsQ0FBQyx1QkFBdUIsQ0FBQyxDQUFBO29CQUNwQyxNQUFNLENBQUMsS0FBSyxDQUFBO2dCQUNkLENBQUM7WUFDSCxDQUFDLENBQUEsQ0FBQTtZQUNELE1BQU0sQ0FBQyxNQUFNLE9BQU8sRUFBRSxDQUFBO1FBQ3hCLENBQUM7S0FBQTtJQUVEOztPQUVHO0lBQ0csVUFBVSxDQUFFLGFBQXFCOztZQUNyQyxNQUFNLENBQUMsTUFBTSxJQUFJLENBQUMsaUJBQWlCLENBQUMsYUFBYSxFQUFFLEdBQUcsQ0FBQyxDQUFBO1FBQ3pELENBQUM7S0FBQTtJQUVEOztPQUVHO0lBQ0csYUFBYSxDQUFFLGFBQXFCOztZQUN4QyxNQUFNLENBQUMsTUFBTSxJQUFJLENBQUMsaUJBQWlCLENBQUMsYUFBYSxFQUFFLE1BQU0sQ0FBQyxDQUFBO1FBQzVELENBQUM7S0FBQTtJQUVEOztPQUVHO0lBQ0gsWUFBWSxDQUFFLGFBQXFCO1FBQ2pDLElBQUksSUFBSSxHQUFHLENBQUMsQ0FBQyxLQUFLLEVBQWdCLENBQUE7UUFDbEMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsYUFBYSxFQUFFLENBQUMsR0FBRyxFQUFFLFVBQVU7WUFDcEQsRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztnQkFDUixJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFBO2dCQUNoQixNQUFNLENBQUE7WUFDUixDQUFDO1lBQ0QsSUFBSSxhQUFhLEdBQWlCLEVBQUUsQ0FBQTtZQUNwQyxHQUFHLENBQUMsQ0FBQyxJQUFJLE1BQU0sSUFBSSxVQUFVLENBQUMsQ0FBQyxDQUFDO2dCQUM5QixJQUFJLFNBQVMsR0FBUSxNQUFNLENBQUEsQ0FBQyxvQkFBb0I7Z0JBQ2hELGFBQWEsQ0FBQyxJQUFJLENBQUM7b0JBQ2pCLE9BQU8sRUFBRSxTQUFTO29CQUNsQixJQUFJLEVBQUUsYUFBYTtvQkFDbkIsS0FBSyxFQUFFLFNBQVMsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDO29CQUMxQixJQUFJLEVBQUUsS0FBSztpQkFDWixDQUFDLENBQUE7WUFDSixDQUFDO1lBQ0QsSUFBSSxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsQ0FBQTtRQUM3QixDQUFDLENBQUMsQ0FBQTtRQUNGLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFBO0lBQ3JCLENBQUM7SUFFRDs7T0FFRztJQUNLLGlCQUFpQixDQUFFLGFBQXFCLEVBQUUsYUFBNkI7UUFDN0UsSUFBSSxJQUFJLEdBQUcsQ0FBQyxDQUFDLEtBQUssRUFBZ0IsQ0FBQTtRQUNsQyxPQUFPLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxhQUFhLEVBQUUsYUFBYSxFQUFFLENBQUMsR0FBRyxFQUFFLFVBQVU7WUFDaEUsRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztnQkFDUixJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFBO2dCQUNoQixNQUFNLENBQUE7WUFDUixDQUFDO1lBQ0QsSUFBSSxhQUFhLEdBQWlCLEVBQUUsQ0FBQTtZQUNwQyxHQUFHLENBQUMsQ0FBQyxJQUFJLFNBQVMsSUFBSSxVQUFVLENBQUMsQ0FBQyxDQUFDO2dCQUNqQyxhQUFhLENBQUMsSUFBSSxDQUFDO29CQUNqQixJQUFJLEVBQUUsYUFBYTtvQkFDbkIsS0FBSyxFQUFFLFVBQVUsQ0FBQyxTQUFTLENBQUM7b0JBQzVCLElBQUksRUFBRSxhQUFhO2lCQUNwQixDQUFDLENBQUE7WUFDSixDQUFDO1lBQ0QsSUFBSSxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsQ0FBQTtRQUM3QixDQUFDLENBQUMsQ0FBQTtRQUNGLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFBO0lBQ3JCLENBQUM7SUFFRDs7T0FFRztJQUNLLGVBQWUsQ0FBRSxXQUF5QjtRQUNoRCxFQUFFLENBQUMsQ0FBQyxXQUFXLEtBQUssUUFBUSxDQUFDLENBQUMsQ0FBQztZQUM3QixJQUFJLENBQUMsV0FBVyxHQUFHLFNBQVMsQ0FBQTtZQUM1QixJQUFJLENBQUMsYUFBYSxHQUFHLEVBQUUsQ0FBQTtZQUN2QixPQUFPLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDLFNBQVMsRUFBRSxTQUFTLENBQUMsQ0FBQyxDQUFBO1FBQ2hELENBQUM7UUFBQyxJQUFJLENBQUMsQ0FBQztZQUNOLE1BQU0sSUFBSSxLQUFLLENBQUMsc0JBQXNCLENBQUMsQ0FBQTtRQUN6QyxDQUFDO0lBQ0gsQ0FBQztDQUNGO0FBNUhELHNCQTRIQyJ9
|
|
@ -1,40 +0,0 @@
|
|||||||
# dnsly
|
|
||||||
smart dns methods written in TypeScript
|
|
||||||
|
|
||||||
## Availabililty
|
|
||||||
[](https://www.npmjs.com/package/dnsly)
|
|
||||||
[](https://GitLab.com/pushrocks/dnsly)
|
|
||||||
[](https://github.com/pushrocks/dnsly)
|
|
||||||
[](https://pushrocks.gitlab.io/dnsly/)
|
|
||||||
|
|
||||||
## Status for master
|
|
||||||
[](https://GitLab.com/pushrocks/dnsly/commits/master)
|
|
||||||
[](https://GitLab.com/pushrocks/dnsly/commits/master)
|
|
||||||
[](https://www.npmjs.com/package/dnsly)
|
|
||||||
[](https://david-dm.org/pushrocks/dnsly)
|
|
||||||
[](https://www.bithound.io/github/pushrocks/dnsly/master/dependencies/npm)
|
|
||||||
[](https://www.bithound.io/github/pushrocks/dnsly)
|
|
||||||
[](https://nodejs.org/dist/latest-v6.x/docs/api/)
|
|
||||||
[](https://nodejs.org/dist/latest-v6.x/docs/api/)
|
|
||||||
[](http://standardjs.com/)
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
import * as dnsly from 'dnsly'
|
|
||||||
|
|
||||||
let myDnsly = new dnsly.Dnsly('google') // uses Google DNS Servers e.g 8.8.8.8
|
|
||||||
myDnsly.getRecord('example.com','AAAA') // returns promise
|
|
||||||
.then((record: dnsly.I_AAAA) => { // AAAA record for google.com, the I_AAAA will give you proper typings for the record return type
|
|
||||||
// do something
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
Use TypeScript for best in class instellisense.
|
|
||||||
|
|
||||||
For further information read the linked docs at the top of this README.
|
|
||||||
|
|
||||||
> MIT licensed | **©** [Lossless GmbH](https://lossless.gmbh)
|
|
||||||
| By using this npm module you agree to our [privacy policy](https://lossless.gmbH/privacy.html)
|
|
||||||
|
|
||||||
[](https://push.rocks)
|
|
@ -1,7 +1,31 @@
|
|||||||
{
|
{
|
||||||
|
"gitzone": {
|
||||||
|
"projectType": "npm",
|
||||||
|
"module": {
|
||||||
|
"githost": "code.foss.global",
|
||||||
|
"gitscope": "push.rocks",
|
||||||
|
"gitrepo": "smartdns",
|
||||||
|
"description": "A TypeScript library for smart DNS methods, supporting various DNS records and providers.",
|
||||||
|
"npmPackagename": "@push.rocks/smartdns",
|
||||||
|
"license": "MIT",
|
||||||
|
"keywords": [
|
||||||
|
"DNS",
|
||||||
|
"TypeScript",
|
||||||
|
"Node.js",
|
||||||
|
"Google DNS",
|
||||||
|
"Cloudflare",
|
||||||
|
"DNS records",
|
||||||
|
"DNS resolution",
|
||||||
|
"DNSSEC"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
"npmci": {
|
"npmci": {
|
||||||
"globalNpmTools": [
|
"npmGlobalTools": [],
|
||||||
"npmts"
|
"npmAccessLevel": "public",
|
||||||
]
|
"npmRegistryUrl": "registry.npmjs.org"
|
||||||
|
},
|
||||||
|
"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"
|
||||||
}
|
}
|
||||||
}
|
}
|
72
package.json
72
package.json
@ -1,33 +1,71 @@
|
|||||||
{
|
{
|
||||||
"name": "dnsly",
|
"name": "@push.rocks/smartdns",
|
||||||
"version": "2.0.9",
|
"version": "6.1.1",
|
||||||
"description": "smart dns methods written in TypeScript",
|
"private": false,
|
||||||
"main": "dist/index.js",
|
"description": "A TypeScript library for smart DNS methods, supporting various DNS records and providers.",
|
||||||
"typings": "dist/index.d.ts",
|
"exports": {
|
||||||
|
".": "./dist_ts_server/index.js",
|
||||||
|
"./server": "./dist_ts_server/index.js",
|
||||||
|
"./client": "./dist_ts_client/index.js"
|
||||||
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "(npmts)"
|
"test": "(tstest test/)",
|
||||||
|
"build": "(tsbuild tsfolders --web --allowimplicitany)",
|
||||||
|
"buildDocs": "tsdoc"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git+ssh://git@gitlab.com/pushrocks/dnsly.git"
|
"url": "https://code.foss.global/push.rocks/smartdns.git"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"dns",
|
"DNS",
|
||||||
"google dns",
|
"TypeScript",
|
||||||
"dns record"
|
"Node.js",
|
||||||
|
"Google DNS",
|
||||||
|
"Cloudflare",
|
||||||
|
"DNS records",
|
||||||
|
"DNS resolution",
|
||||||
|
"DNSSEC"
|
||||||
],
|
],
|
||||||
"author": "Lossless GmbH",
|
"author": "Lossless GmbH",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://gitlab.com/pushrocks/dnsly/issues"
|
"url": "https://gitlab.com/pushrocks/dnsly/issues"
|
||||||
},
|
},
|
||||||
"homepage": "https://gitlab.com/pushrocks/dnsly#README",
|
"homepage": "https://code.foss.global/push.rocks/smartdns",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"beautylog": "^6.1.10",
|
"@push.rocks/smartdelay": "^3.0.1",
|
||||||
"smartdelay": "^1.0.3",
|
"@push.rocks/smartenv": "^5.0.5",
|
||||||
"smartq": "^1.1.6",
|
"@push.rocks/smartpromise": "^4.0.4",
|
||||||
"tapbundle": "^1.1.1",
|
"@push.rocks/smartrequest": "^2.0.15",
|
||||||
"typings-global": "^1.0.19"
|
"@tsclass/tsclass": "^4.1.2",
|
||||||
|
"@types/dns-packet": "^5.6.5",
|
||||||
|
"@types/elliptic": "^6.4.18",
|
||||||
|
"dns-packet": "^5.6.1",
|
||||||
|
"elliptic": "^6.5.7",
|
||||||
|
"minimatch": "^10.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {}
|
"devDependencies": {
|
||||||
|
"@git.zone/tsbuild": "^2.1.84",
|
||||||
|
"@git.zone/tsrun": "^1.2.49",
|
||||||
|
"@git.zone/tstest": "^1.0.77",
|
||||||
|
"@push.rocks/tapbundle": "^5.2.0",
|
||||||
|
"@types/node": "^22.5.5"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"ts/**/*",
|
||||||
|
"ts_web/**/*",
|
||||||
|
"dist/**/*",
|
||||||
|
"dist_*/**/*",
|
||||||
|
"dist_ts/**/*",
|
||||||
|
"dist_ts_web/**/*",
|
||||||
|
"assets/**/*",
|
||||||
|
"cli.js",
|
||||||
|
"npmextra.json",
|
||||||
|
"readme.md"
|
||||||
|
],
|
||||||
|
"browserslist": [
|
||||||
|
"last 1 chrome versions"
|
||||||
|
],
|
||||||
|
"type": "module"
|
||||||
}
|
}
|
||||||
|
6987
pnpm-lock.yaml
generated
Normal file
6987
pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
1
readme.hints.md
Normal file
1
readme.hints.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
|
137
readme.md
137
readme.md
@ -1,29 +1,124 @@
|
|||||||
# dnsly
|
# @push.rocks/smartdns
|
||||||
|
|
||||||
smart dns methods written in TypeScript
|
smart dns methods written in TypeScript
|
||||||
|
|
||||||
## Availabililty
|
## Install
|
||||||
[](https://www.npmjs.com/package/dnsly)
|
|
||||||
[](https://GitLab.com/pushrocks/dnsly)
|
|
||||||
[](https://github.com/pushrocks/dnsly)
|
|
||||||
[](https://pushrocks.gitlab.io/dnsly/)
|
|
||||||
|
|
||||||
## Status for master
|
To install `@push.rocks/smartdns`, use the following command with npm:
|
||||||
[](https://GitLab.com/pushrocks/dnsly/commits/master)
|
|
||||||
[](https://GitLab.com/pushrocks/dnsly/commits/master)
|
```bash
|
||||||
[](https://www.npmjs.com/package/dnsly)
|
npm install @push.rocks/smartdns --save
|
||||||
[](https://david-dm.org/pushrocks/dnsly)
|
```
|
||||||
[](https://www.bithound.io/github/pushrocks/dnsly/master/dependencies/npm)
|
|
||||||
[](https://www.bithound.io/github/pushrocks/dnsly)
|
Or with `yarn`:
|
||||||
[](https://nodejs.org/dist/latest-v6.x/docs/api/)
|
|
||||||
[](https://nodejs.org/dist/latest-v6.x/docs/api/)
|
```bash
|
||||||
[](http://standardjs.com/)
|
yarn add @push.rocks/smartdns
|
||||||
|
```
|
||||||
|
|
||||||
|
Make sure you have a TypeScript environment setup to utilize the library effectively.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
Use TypeScript for best in class instellisense.
|
|
||||||
|
|
||||||
For further information read the linked docs at the top of this README.
|
`@push.rocks/smartdns` is a comprehensive library aimed at facilitating smart DNS operations, leveraging TypeScript for enhanced development experience. This section aims to cover several real-world scenarios demonstrating the library's capabilities, from basic DNS lookups to more advanced DNS management tasks.
|
||||||
|
|
||||||
> MIT licensed | **©** [Lossless GmbH](https://lossless.gmbh)
|
### Getting Started
|
||||||
| By using this npm module you agree to our [privacy policy](https://lossless.gmbH/privacy.html)
|
|
||||||
|
|
||||||
[](https://push.rocks)
|
First, ensure you import the module into your TypeScript project:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { Smartdns } from '@push.rocks/smartdns';
|
||||||
|
```
|
||||||
|
|
||||||
|
### Basic DNS Record Lookup
|
||||||
|
|
||||||
|
Often, the need arises to fetch various DNS records for a domain. `@push.rocks/smartdns` simplifies this by providing intuitive methods.
|
||||||
|
|
||||||
|
#### Fetching A Records
|
||||||
|
|
||||||
|
To fetch an "A" record for a domain:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const dnsManager = new Smartdns({});
|
||||||
|
const aRecords = await dnsManager.getRecordsA('example.com');
|
||||||
|
console.log(aRecords);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Fetching AAAA Records
|
||||||
|
|
||||||
|
Similarly, for "AAAA" records:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const aaaaRecords = await dnsManager.getRecordsAAAA('example.com');
|
||||||
|
console.log(aaaaRecords);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Advanced DNS Management
|
||||||
|
|
||||||
|
Beyond simple queries, `@push.rocks/smartdns` offers functionalities suitable for more complex DNS management scenarios.
|
||||||
|
|
||||||
|
#### Checking DNS Propagation
|
||||||
|
|
||||||
|
When changing DNS records, ensuring that the new records have propagated fully is crucial. `@push.rocks/smartdns` facilitates this with a method to check a DNS record until it is available globally.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const recordType = 'TXT'; // Record type: A, AAAA, CNAME, TXT etc.
|
||||||
|
const expectedValue = 'your_expected_value';
|
||||||
|
const isAvailable = await dnsManager.checkUntilAvailable('example.com', recordType, expectedValue);
|
||||||
|
|
||||||
|
if (isAvailable) {
|
||||||
|
console.log('Record propagated successfully.');
|
||||||
|
} else {
|
||||||
|
console.log('Record propagation failed or timed out.');
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Leveraging DNS for Application Logic
|
||||||
|
|
||||||
|
DNS records can serve beyond mere domain-to-IP resolution; they can be instrumental in application logic, such as feature flagging or environment-specific configurations.
|
||||||
|
|
||||||
|
#### Example: Feature Flagging via TXT Records
|
||||||
|
|
||||||
|
Consider leveraging TXT records for enabling/disabling features dynamically without deploying new code.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const txtRecords = await dnsManager.getRecordsTxt('features.example.com');
|
||||||
|
const featureFlags = txtRecords.reduce((acc, record) => {
|
||||||
|
const [flag, isEnabled] = record.value.split('=');
|
||||||
|
acc[flag] = isEnabled === 'true';
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
if (featureFlags['NewFeature']) {
|
||||||
|
// Logic to enable the new feature
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Conclusion
|
||||||
|
|
||||||
|
`@push.rocks/smartdns` offers a versatile set of tools for DNS querying and management, tailored for applications at any scale. The examples provided illustrate the library's potential use cases, highlighting its applicability in various scenarios from basic lookups to facilitating complex application features through DNS.
|
||||||
|
|
||||||
|
For the full spectrum of functionalities, including detailed method documentation and additional use cases, consult the module's [TypeDoc documentation](https://pushrocks.gitlab.io/smartdns/). This will serve as a comprehensive guide to leveraging `@push.rocks/smartdns` effectively in your projects.
|
||||||
|
|
||||||
|
Remember, DNS changes might take time to propagate worldwide, and the utility methods provided by `@push.rocks/smartdns` for checking record availability will be invaluable in managing these changes seamlessly.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## License and Legal Information
|
||||||
|
|
||||||
|
This 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.
|
||||||
|
|
||||||
|
**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.
|
||||||
|
|
||||||
|
### Trademarks
|
||||||
|
|
||||||
|
This 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.
|
||||||
|
|
||||||
|
### Company Information
|
||||||
|
|
||||||
|
Task Venture Capital GmbH
|
||||||
|
Registered at District court Bremen HRB 35230 HB, Germany
|
||||||
|
|
||||||
|
For any legal inquiries or if you require further information, please contact us via email at hello@task.vc.
|
||||||
|
|
||||||
|
By 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.
|
||||||
|
79
test/test.client.ts
Normal file
79
test/test.client.ts
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
import { expect, tap } from '@push.rocks/tapbundle';
|
||||||
|
|
||||||
|
import * as smartdns from '../ts_client/index.js';
|
||||||
|
|
||||||
|
let testDnsly: smartdns.Smartdns;
|
||||||
|
|
||||||
|
tap.test('should create an instance of Dnsly', async () => {
|
||||||
|
testDnsly = new smartdns.Smartdns({});
|
||||||
|
expect(testDnsly).toBeInstanceOf(smartdns.Smartdns);
|
||||||
|
});
|
||||||
|
|
||||||
|
tap.test('should get an A DNS Record', async () => {
|
||||||
|
return expect(await testDnsly.getRecordsA('dnsly_a.bleu.de')).toEqual([
|
||||||
|
{
|
||||||
|
name: 'dnsly_a.bleu.de',
|
||||||
|
value: '127.0.0.1',
|
||||||
|
dnsSecEnabled: false,
|
||||||
|
type: 'A',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
tap.test('should get an AAAA Record', async () => {
|
||||||
|
return expect(await testDnsly.getRecordsAAAA('dnsly_aaaa.bleu.de')).toEqual([
|
||||||
|
{
|
||||||
|
name: 'dnsly_aaaa.bleu.de',
|
||||||
|
value: '::1',
|
||||||
|
dnsSecEnabled: false,
|
||||||
|
type: 'AAAA',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
tap.test('should get a txt record', async () => {
|
||||||
|
return expect(await testDnsly.getRecordsTxt('dnsly_txt.bleu.de')).toEqual([
|
||||||
|
{
|
||||||
|
name: 'dnsly_txt.bleu.de',
|
||||||
|
value: 'sometext_txt',
|
||||||
|
type: 'TXT',
|
||||||
|
dnsSecEnabled: false,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
tap.test('should, get a mx record for a domain', async () => {
|
||||||
|
const res = await testDnsly.getRecords('bleu.de', 'MX');
|
||||||
|
console.log(res);
|
||||||
|
});
|
||||||
|
|
||||||
|
tap.test('should check until DNS is available', async () => {
|
||||||
|
return expect(
|
||||||
|
await testDnsly.checkUntilAvailable('dnsly_txt.bleu.de', 'TXT', 'sometext_txt')
|
||||||
|
).toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
tap.test('should check until DNS is available an return false if it fails', async () => {
|
||||||
|
return expect(
|
||||||
|
await testDnsly.checkUntilAvailable('dnsly_txt.bleu.de', 'TXT', 'sometext_txt2')
|
||||||
|
).toBeFalse();
|
||||||
|
});
|
||||||
|
|
||||||
|
tap.test('should check until DNS is available an return false if it fails', async () => {
|
||||||
|
return expect(
|
||||||
|
await testDnsly.checkUntilAvailable('dnsly_txtNotThere.bleu.de', 'TXT', 'sometext_txt2')
|
||||||
|
).toBeFalse();
|
||||||
|
});
|
||||||
|
|
||||||
|
tap.test('should get name server for hostname', async () => {
|
||||||
|
let result = await testDnsly.getNameServers('bleu.de');
|
||||||
|
console.log(result);
|
||||||
|
});
|
||||||
|
|
||||||
|
tap.test('should detect dns sec', async () => {
|
||||||
|
const result = await testDnsly.getRecordsA('lossless.com');
|
||||||
|
console.log(result[0]);
|
||||||
|
expect(result[0].dnsSecEnabled).toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
tap.start();
|
163
test/test.server.ts
Normal file
163
test/test.server.ts
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
import { expect, tap } from '@push.rocks/tapbundle';
|
||||||
|
import { tapNodeTools } from '@push.rocks/tapbundle/node';
|
||||||
|
|
||||||
|
import * as dnsPacket from 'dns-packet';
|
||||||
|
import * as https from 'https';
|
||||||
|
import * as dgram from 'dgram';
|
||||||
|
|
||||||
|
import * as smartdns from '../ts_server/index.js';
|
||||||
|
|
||||||
|
let dnsServer: smartdns.DnsServer;
|
||||||
|
|
||||||
|
tap.test('should create an instance of DnsServer', async () => {
|
||||||
|
// Use valid options
|
||||||
|
const httpsData = await tapNodeTools.createHttpsCert();
|
||||||
|
dnsServer = new smartdns.DnsServer({
|
||||||
|
httpsKey: httpsData.key,
|
||||||
|
httpsCert: httpsData.cert,
|
||||||
|
httpsPort: 8080,
|
||||||
|
udpPort: 8081,
|
||||||
|
});
|
||||||
|
expect(dnsServer).toBeInstanceOf(smartdns.DnsServer);
|
||||||
|
});
|
||||||
|
|
||||||
|
tap.test('should start the server', async () => {
|
||||||
|
await dnsServer.start();
|
||||||
|
// @ts-ignore
|
||||||
|
expect(dnsServer.httpsServer).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
tap.test('lets add a handler', async () => {
|
||||||
|
dnsServer.registerHandler('*.bleu.de', ['A'], (question) => {
|
||||||
|
return {
|
||||||
|
name: question.name,
|
||||||
|
type: 'A',
|
||||||
|
class: 'IN',
|
||||||
|
ttl: 300,
|
||||||
|
data: '127.0.0.1',
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
const response = dnsServer.processDnsRequest({
|
||||||
|
type: 'query',
|
||||||
|
id: 1,
|
||||||
|
flags: 0,
|
||||||
|
questions: [
|
||||||
|
{
|
||||||
|
name: 'dnsly_a.bleu.de',
|
||||||
|
type: 'A',
|
||||||
|
class: 'IN',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
answers: [],
|
||||||
|
});
|
||||||
|
expect(response.answers[0]).toEqual({
|
||||||
|
name: 'dnsly_a.bleu.de',
|
||||||
|
type: 'A',
|
||||||
|
class: 'IN',
|
||||||
|
ttl: 300,
|
||||||
|
data: '127.0.0.1',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
tap.test('lets query over https', async () => {
|
||||||
|
const query = dnsPacket.encode({
|
||||||
|
type: 'query',
|
||||||
|
id: 2,
|
||||||
|
flags: dnsPacket.RECURSION_DESIRED,
|
||||||
|
questions: [
|
||||||
|
{
|
||||||
|
name: 'dnsly_a.bleu.de',
|
||||||
|
type: 'A',
|
||||||
|
class: 'IN',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const response = await fetch('https://localhost:8080/dns-query', {
|
||||||
|
method: 'POST',
|
||||||
|
body: query,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/dns-message',
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(response.status).toEqual(200);
|
||||||
|
|
||||||
|
const responseData = await response.arrayBuffer();
|
||||||
|
const dnsResponse = dnsPacket.decode(Buffer.from(responseData));
|
||||||
|
|
||||||
|
console.log(dnsResponse.answers[0]);
|
||||||
|
|
||||||
|
expect(dnsResponse.answers[0]).toEqual({
|
||||||
|
name: 'dnsly_a.bleu.de',
|
||||||
|
type: 'A',
|
||||||
|
class: 'IN',
|
||||||
|
ttl: 300,
|
||||||
|
flush: false,
|
||||||
|
data: '127.0.0.1',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
tap.test('lets query over udp', async () => {
|
||||||
|
const client = dgram.createSocket('udp4');
|
||||||
|
|
||||||
|
const query = dnsPacket.encode({
|
||||||
|
type: 'query',
|
||||||
|
id: 3,
|
||||||
|
flags: dnsPacket.RECURSION_DESIRED,
|
||||||
|
questions: [
|
||||||
|
{
|
||||||
|
name: 'dnsly_a.bleu.de',
|
||||||
|
type: 'A',
|
||||||
|
class: 'IN',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const responsePromise = new Promise<dnsPacket.Packet>((resolve, reject) => {
|
||||||
|
client.on('message', (msg) => {
|
||||||
|
const dnsResponse = dnsPacket.decode(msg);
|
||||||
|
resolve(dnsResponse);
|
||||||
|
client.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
client.on('error', (err) => {
|
||||||
|
reject(err);
|
||||||
|
client.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
client.send(query, 8081, 'localhost', (err) => {
|
||||||
|
if (err) {
|
||||||
|
reject(err);
|
||||||
|
client.close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const dnsResponse = await responsePromise;
|
||||||
|
|
||||||
|
console.log(dnsResponse.answers[0]);
|
||||||
|
|
||||||
|
expect(dnsResponse.answers[0]).toEqual({
|
||||||
|
name: 'dnsly_a.bleu.de',
|
||||||
|
type: 'A',
|
||||||
|
class: 'IN',
|
||||||
|
ttl: 300,
|
||||||
|
flush: false,
|
||||||
|
data: '127.0.0.1',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
tap.test('should run for a while', async (toolsArg) => {
|
||||||
|
await toolsArg.delayFor(1000);
|
||||||
|
});
|
||||||
|
|
||||||
|
tap.test('should stop the server', async () => {
|
||||||
|
await dnsServer.stop();
|
||||||
|
// @ts-ignore
|
||||||
|
expect(dnsServer.httpsServer).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
await tap.start();
|
56
test/test.ts
56
test/test.ts
@ -1,56 +0,0 @@
|
|||||||
import { expect, tap } from 'tapbundle'
|
|
||||||
|
|
||||||
import * as dnsly from '../dist/index'
|
|
||||||
|
|
||||||
let testDnsly: dnsly.Dnsly
|
|
||||||
|
|
||||||
tap.test('should create an instance of Dnsly', async () => {
|
|
||||||
testDnsly = new dnsly.Dnsly('google')
|
|
||||||
expect(testDnsly).to.be.instanceOf(dnsly.Dnsly)
|
|
||||||
})
|
|
||||||
|
|
||||||
tap.test('should get an A DNS Record', async () => {
|
|
||||||
return expect(testDnsly.getRecordA('dnsly_a.bleu.de')).to.eventually.deep.equal([{
|
|
||||||
name: 'dnsly_a.bleu.de',
|
|
||||||
value: '127.0.0.1',
|
|
||||||
type: 'A'
|
|
||||||
}])
|
|
||||||
})
|
|
||||||
|
|
||||||
tap.test('should get an AAAA Record', async () => {
|
|
||||||
return expect(testDnsly.getRecordAAAA('dnsly_aaaa.bleu.de')).to.eventually.deep.equal([{
|
|
||||||
name: 'dnsly_aaaa.bleu.de',
|
|
||||||
value: '::1',
|
|
||||||
type: 'AAAA'
|
|
||||||
}])
|
|
||||||
})
|
|
||||||
|
|
||||||
tap.test('should get a txt record', async () => {
|
|
||||||
return expect(testDnsly.getRecordTxt('dnsly_txt.bleu.de')).to.eventually.deep.equal([{
|
|
||||||
chunked: ['sometext_txt'],
|
|
||||||
name: 'dnsly_txt.bleu.de',
|
|
||||||
value: 'sometext_txt',
|
|
||||||
type: 'TXT'
|
|
||||||
}])
|
|
||||||
})
|
|
||||||
|
|
||||||
tap.test('should, get a mx record for a domain', async () => {
|
|
||||||
let res = await testDnsly.getRecord('google.com', 'MX')
|
|
||||||
console.log(res)
|
|
||||||
})
|
|
||||||
|
|
||||||
tap.test('should check until DNS is available', async () => {
|
|
||||||
return expect(testDnsly.checkUntilAvailable('dnsly_txt.bleu.de', 'TXT', 'sometext_txt')).to.eventually.be.true
|
|
||||||
})
|
|
||||||
|
|
||||||
tap.test('should check until DNS is available an return false if it fails', async () => {
|
|
||||||
return expect(testDnsly.checkUntilAvailable('dnsly_txt.bleu.de', 'TXT', 'sometext_txt2')).to.eventually.be.false
|
|
||||||
})
|
|
||||||
|
|
||||||
tap.test('should check until DNS is available an return false if it fails', async () => {
|
|
||||||
return expect(
|
|
||||||
testDnsly.checkUntilAvailable('dnsly_txtNotThere.bleu.de', 'TXT', 'sometext_txt2')
|
|
||||||
).to.eventually.be.false
|
|
||||||
})
|
|
||||||
|
|
||||||
tap.start()
|
|
@ -1,10 +0,0 @@
|
|||||||
import 'typings-global'
|
|
||||||
import * as beautylog from 'beautylog'
|
|
||||||
import * as dns from 'dns'
|
|
||||||
import * as smartdelay from 'smartdelay'
|
|
||||||
|
|
||||||
export {
|
|
||||||
beautylog,
|
|
||||||
dns,
|
|
||||||
smartdelay
|
|
||||||
}
|
|
150
ts/index.ts
150
ts/index.ts
@ -1,150 +0,0 @@
|
|||||||
import * as q from 'smartq'
|
|
||||||
import * as plugins from './dnsly.plugins'
|
|
||||||
|
|
||||||
export type TDnsProvider = 'google'
|
|
||||||
export type TDnsRecordType = 'A'
|
|
||||||
| 'AAAA'
|
|
||||||
| 'CNAME'
|
|
||||||
| 'PTR'
|
|
||||||
| 'MX'
|
|
||||||
| 'NAPTR'
|
|
||||||
| 'NS'
|
|
||||||
| 'SOA'
|
|
||||||
| 'SRV'
|
|
||||||
| 'TXT'
|
|
||||||
|
|
||||||
export interface IDnsRecord {
|
|
||||||
chunked?: string[]
|
|
||||||
name: string
|
|
||||||
type: TDnsRecordType
|
|
||||||
value: string
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* class dnsly offers methods for working with dns from a dns provider like Google DNS
|
|
||||||
*/
|
|
||||||
export class Dnsly {
|
|
||||||
dnsServerIp: string
|
|
||||||
dnsServerPort: number
|
|
||||||
/**
|
|
||||||
* constructor for class dnsly
|
|
||||||
*/
|
|
||||||
constructor(dnsProviderArg: TDnsProvider = 'google') {
|
|
||||||
this._setDnsProvider(dnsProviderArg)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* gets a record
|
|
||||||
*/
|
|
||||||
async getRecord (recordNameArg: string, recordTypeArg: TDnsRecordType): Promise<IDnsRecord[]> {
|
|
||||||
switch (recordTypeArg) {
|
|
||||||
case 'TXT':
|
|
||||||
return await this.getRecordTxt(recordNameArg)
|
|
||||||
case 'A':
|
|
||||||
return await this.getRecordA(recordNameArg)
|
|
||||||
case 'AAAA':
|
|
||||||
return await this.getRecordAAAA(recordNameArg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async checkUntilAvailable (recordNameArg: string, recordTypeArg: TDnsRecordType, expectedValue: string) {
|
|
||||||
let cycleArg = 0
|
|
||||||
let doCheck = async () => {
|
|
||||||
if (cycleArg < 30) {
|
|
||||||
cycleArg++
|
|
||||||
try {
|
|
||||||
let myRecordArray = await this.getRecord(recordNameArg, recordTypeArg)
|
|
||||||
let myRecord = myRecordArray[0].value
|
|
||||||
if (myRecord === expectedValue) {
|
|
||||||
return true
|
|
||||||
} else {
|
|
||||||
await plugins.smartdelay.delayFor(500)
|
|
||||||
return await doCheck()
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
await plugins.smartdelay.delayFor(500)
|
|
||||||
return await doCheck()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
console.log('failed permanently...')
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return await doCheck()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* get A Dns Record
|
|
||||||
*/
|
|
||||||
async getRecordA (recordNameArg: string): Promise<IDnsRecord[]> {
|
|
||||||
return await this.getOrdinaryRecord(recordNameArg, 'A')
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* get AAAA Record
|
|
||||||
*/
|
|
||||||
async getRecordAAAA (recordNameArg: string) {
|
|
||||||
return await this.getOrdinaryRecord(recordNameArg, 'AAAA')
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* gets a txt record
|
|
||||||
*/
|
|
||||||
getRecordTxt (recordNameArg: string): Promise<IDnsRecord[]> {
|
|
||||||
let done = q.defer<IDnsRecord[]>()
|
|
||||||
plugins.dns.resolveTxt(recordNameArg, (err, recordsArg) => {
|
|
||||||
if (err) {
|
|
||||||
done.reject(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
let responseArray: IDnsRecord[] = []
|
|
||||||
for (let record of recordsArg) {
|
|
||||||
let recordAny: any = record // fix wrong typings
|
|
||||||
responseArray.push({
|
|
||||||
chunked: recordAny,
|
|
||||||
name: recordNameArg,
|
|
||||||
value: recordAny.join(' '),
|
|
||||||
type: 'TXT'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
done.resolve(responseArray)
|
|
||||||
})
|
|
||||||
return done.promise
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* get oridinary record
|
|
||||||
*/
|
|
||||||
private getOrdinaryRecord (recordNameArg: string, recordTypeArg: TDnsRecordType): Promise<IDnsRecord[]> {
|
|
||||||
let done = q.defer<IDnsRecord[]>()
|
|
||||||
plugins.dns.resolve(recordNameArg, recordTypeArg, (err, recordsArg) => {
|
|
||||||
if (err) {
|
|
||||||
done.reject(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
let responseArray: IDnsRecord[] = []
|
|
||||||
for (let recordKey in recordsArg) {
|
|
||||||
responseArray.push({
|
|
||||||
name: recordNameArg,
|
|
||||||
value: recordsArg[recordKey],
|
|
||||||
type: recordTypeArg
|
|
||||||
})
|
|
||||||
}
|
|
||||||
done.resolve(responseArray)
|
|
||||||
})
|
|
||||||
return done.promise
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* set the DNS provider
|
|
||||||
*/
|
|
||||||
private _setDnsProvider (dnsProvider: TDnsProvider) {
|
|
||||||
if (dnsProvider === 'google') {
|
|
||||||
this.dnsServerIp = '8.8.8.8'
|
|
||||||
this.dnsServerPort = 53
|
|
||||||
plugins.dns.setServers(['8.8.8.8', '8.8.4.4'])
|
|
||||||
} else {
|
|
||||||
throw new Error('unknown dns provider')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
8
ts_client/00_commitinfo_data.ts
Normal file
8
ts_client/00_commitinfo_data.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
/**
|
||||||
|
* autocreated commitinfo by @push.rocks/commitinfo
|
||||||
|
*/
|
||||||
|
export const commitinfo = {
|
||||||
|
name: '@push.rocks/smartdns',
|
||||||
|
version: '5.0.4',
|
||||||
|
description: 'smart dns methods written in TypeScript'
|
||||||
|
}
|
229
ts_client/classes.dnsclient.ts
Normal file
229
ts_client/classes.dnsclient.ts
Normal file
@ -0,0 +1,229 @@
|
|||||||
|
import * as plugins from './dnsly.plugins.js';
|
||||||
|
|
||||||
|
export type TDnsProvider = 'google' | 'cloudflare';
|
||||||
|
|
||||||
|
export const makeNodeProcessUseDnsProvider = (providerArg: TDnsProvider) => {
|
||||||
|
switch (providerArg) {
|
||||||
|
case 'cloudflare':
|
||||||
|
plugins.dns.setServers([
|
||||||
|
'1.1.1.1',
|
||||||
|
'1.0.0.1',
|
||||||
|
'[2606:4700:4700::1111]',
|
||||||
|
'[2606:4700:4700::1001]',
|
||||||
|
]);
|
||||||
|
break;
|
||||||
|
case 'google':
|
||||||
|
plugins.dns.setServers([
|
||||||
|
'8.8.8.8',
|
||||||
|
'8.8.4.4',
|
||||||
|
'[2001:4860:4860::8888]',
|
||||||
|
'[2606:4700:4700::1001]',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface ISmartDnsConstructorOptions {}
|
||||||
|
|
||||||
|
export interface IDnsJsonResponse {
|
||||||
|
Status: number;
|
||||||
|
TC: boolean;
|
||||||
|
RD: boolean;
|
||||||
|
RA: boolean;
|
||||||
|
AD: boolean;
|
||||||
|
CD: boolean;
|
||||||
|
Question: Array<{ name: string; type: number }>;
|
||||||
|
Answer: Array<{ name: string; type: number; TTL: number; data: string }>;
|
||||||
|
Additional: [];
|
||||||
|
Comment: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* class dnsly offers methods for working with dns from a dns provider like Google DNS
|
||||||
|
*/
|
||||||
|
export class Smartdns {
|
||||||
|
public dnsServerIp: string;
|
||||||
|
public dnsServerPort: number;
|
||||||
|
|
||||||
|
public dnsTypeMap: { [key: string]: number } = {
|
||||||
|
A: 1,
|
||||||
|
AAAA: 28,
|
||||||
|
CNAME: 5,
|
||||||
|
MX: 15,
|
||||||
|
TXT: 16,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* constructor for class dnsly
|
||||||
|
*/
|
||||||
|
constructor(optionsArg: ISmartDnsConstructorOptions) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* check a dns record until it has propagated to Google DNS
|
||||||
|
* should be considerably fast
|
||||||
|
* @param recordNameArg
|
||||||
|
* @param recordTypeArg
|
||||||
|
* @param expectedValue
|
||||||
|
*/
|
||||||
|
public async checkUntilAvailable(
|
||||||
|
recordNameArg: string,
|
||||||
|
recordTypeArg: plugins.tsclass.network.TDnsRecordType,
|
||||||
|
expectedValue: string,
|
||||||
|
cyclesArg: number = 50,
|
||||||
|
intervalArg: number = 500
|
||||||
|
) {
|
||||||
|
let runCycles = 0;
|
||||||
|
const doCheck = async () => {
|
||||||
|
if (runCycles < cyclesArg) {
|
||||||
|
runCycles++;
|
||||||
|
try {
|
||||||
|
let myRecordArray: plugins.tsclass.network.IDnsRecord[];
|
||||||
|
if (runCycles % 2 === 0 || !plugins.dns) {
|
||||||
|
myRecordArray = await this.getRecords(recordNameArg, recordTypeArg, 0);
|
||||||
|
} else {
|
||||||
|
myRecordArray = await this.getRecordWithNodeDNS(recordNameArg, recordTypeArg);
|
||||||
|
}
|
||||||
|
const myRecord = myRecordArray[0].value;
|
||||||
|
if (myRecord === expectedValue) {
|
||||||
|
console.log(
|
||||||
|
`smartdns: .checkUntilAvailable() verified that wanted >>>${recordTypeArg}<<< record exists for >>>${recordNameArg}<<< with value >>>${expectedValue}<<<`
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
await plugins.smartdelay.delayFor(intervalArg);
|
||||||
|
return await doCheck();
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
// console.log(err);
|
||||||
|
await plugins.smartdelay.delayFor(intervalArg);
|
||||||
|
return await doCheck();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log(
|
||||||
|
`smartdns: .checkUntilAvailable() failed permanently for ${recordNameArg} with value ${recordTypeArg} - ${expectedValue}...`
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return await doCheck();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get A Dns Record
|
||||||
|
*/
|
||||||
|
public async getRecordsA(recordNameArg: string): Promise<plugins.tsclass.network.IDnsRecord[]> {
|
||||||
|
return await this.getRecords(recordNameArg, 'A');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get AAAA Record
|
||||||
|
*/
|
||||||
|
public async getRecordsAAAA(recordNameArg: string) {
|
||||||
|
return await this.getRecords(recordNameArg, 'AAAA');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gets a txt record
|
||||||
|
*/
|
||||||
|
public async getRecordsTxt(recordNameArg: string): Promise<plugins.tsclass.network.IDnsRecord[]> {
|
||||||
|
return await this.getRecords(recordNameArg, 'TXT');
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getRecords(
|
||||||
|
recordNameArg: string,
|
||||||
|
recordTypeArg: plugins.tsclass.network.TDnsRecordType,
|
||||||
|
retriesCounterArg = 20
|
||||||
|
): Promise<plugins.tsclass.network.IDnsRecord[]> {
|
||||||
|
const requestUrl = `https://cloudflare-dns.com/dns-query?name=${recordNameArg}&type=${recordTypeArg}&do=1`;
|
||||||
|
const returnArray: plugins.tsclass.network.IDnsRecord[] = [];
|
||||||
|
const getResponseBody = async (counterArg = 0): Promise<IDnsJsonResponse> => {
|
||||||
|
const response = await plugins.smartrequest.request(requestUrl, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
accept: 'application/dns-json',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const responseBody: IDnsJsonResponse = response.body;
|
||||||
|
if (responseBody?.Status !== 0 && counterArg < retriesCounterArg) {
|
||||||
|
await plugins.smartdelay.delayFor(500);
|
||||||
|
return getResponseBody(counterArg++);
|
||||||
|
} else {
|
||||||
|
return responseBody;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const responseBody = await getResponseBody();
|
||||||
|
if (!responseBody.Answer || !typeof responseBody.Answer[Symbol.iterator]) {
|
||||||
|
return returnArray;
|
||||||
|
}
|
||||||
|
for (const dnsEntry of responseBody.Answer) {
|
||||||
|
if (dnsEntry.data.startsWith('"') && dnsEntry.data.endsWith('"')) {
|
||||||
|
dnsEntry.data = dnsEntry.data.replace(/^"(.*)"$/, '$1');
|
||||||
|
}
|
||||||
|
if (dnsEntry.name.endsWith('.')) {
|
||||||
|
dnsEntry.name = dnsEntry.name.substring(0, dnsEntry.name.length - 1);
|
||||||
|
}
|
||||||
|
returnArray.push({
|
||||||
|
name: dnsEntry.name,
|
||||||
|
type: this.convertDnsTypeNumberToTypeName(dnsEntry.type),
|
||||||
|
dnsSecEnabled: responseBody.AD,
|
||||||
|
value: dnsEntry.data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// console.log(responseBody);
|
||||||
|
return returnArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gets a record using nodejs dns resolver
|
||||||
|
*/
|
||||||
|
public async getRecordWithNodeDNS(
|
||||||
|
recordNameArg: string,
|
||||||
|
recordTypeArg: plugins.tsclass.network.TDnsRecordType
|
||||||
|
): Promise<plugins.tsclass.network.IDnsRecord[]> {
|
||||||
|
const done = plugins.smartpromise.defer<plugins.tsclass.network.IDnsRecord[]>();
|
||||||
|
plugins.dns.resolve(recordNameArg, recordTypeArg, (err, recordsArg) => {
|
||||||
|
if (err) {
|
||||||
|
done.reject(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const returnArray: plugins.tsclass.network.IDnsRecord[] = [];
|
||||||
|
for (const recordKey in recordsArg) {
|
||||||
|
returnArray.push({
|
||||||
|
name: recordNameArg,
|
||||||
|
value: recordsArg[recordKey][0],
|
||||||
|
type: recordTypeArg,
|
||||||
|
dnsSecEnabled: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
done.resolve(returnArray);
|
||||||
|
});
|
||||||
|
return done.promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getNameServers(domainNameArg: string): Promise<string[]> {
|
||||||
|
const done = plugins.smartpromise.defer<string[]>();
|
||||||
|
plugins.dns.resolveNs(domainNameArg, (err, result) => {
|
||||||
|
if (!err) {
|
||||||
|
done.resolve(result);
|
||||||
|
} else {
|
||||||
|
console.log(err);
|
||||||
|
done.reject(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return await done.promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
public convertDnsTypeNameToTypeNumber(dnsTypeNameArg: string): number {
|
||||||
|
return this.dnsTypeMap[dnsTypeNameArg];
|
||||||
|
}
|
||||||
|
|
||||||
|
public convertDnsTypeNumberToTypeName(
|
||||||
|
dnsTypeNumberArg: number
|
||||||
|
): plugins.tsclass.network.TDnsRecordType {
|
||||||
|
for (const key in this.dnsTypeMap) {
|
||||||
|
if (this.dnsTypeMap[key] === dnsTypeNumberArg) {
|
||||||
|
return key as plugins.tsclass.network.TDnsRecordType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
18
ts_client/dnsly.plugins.ts
Normal file
18
ts_client/dnsly.plugins.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import * as smartenv from '@push.rocks/smartenv';
|
||||||
|
const smartenvInstance = new smartenv.Smartenv();
|
||||||
|
// node native scope
|
||||||
|
import type dnsType from 'dns';
|
||||||
|
const dns: typeof dnsType = await smartenvInstance.getSafeNodeModule('dns');
|
||||||
|
|
||||||
|
export { dns };
|
||||||
|
|
||||||
|
// pushrocks scope
|
||||||
|
import * as smartdelay from '@push.rocks/smartdelay';
|
||||||
|
import * as smartpromise from '@push.rocks/smartpromise';
|
||||||
|
import * as smartrequest from '@push.rocks/smartrequest';
|
||||||
|
|
||||||
|
export { smartdelay, smartenv, smartpromise, smartrequest };
|
||||||
|
|
||||||
|
import * as tsclass from '@tsclass/tsclass';
|
||||||
|
|
||||||
|
export { tsclass };
|
1
ts_client/index.ts
Normal file
1
ts_client/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './classes.dnsclient.js';
|
147
ts_server/classes.dnsserver.ts
Normal file
147
ts_server/classes.dnsserver.ts
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
import * as plugins from './plugins.js';
|
||||||
|
|
||||||
|
interface IDnsServerOptions {
|
||||||
|
httpsKey: string;
|
||||||
|
httpsCert: string;
|
||||||
|
httpsPort: number;
|
||||||
|
udpPort: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IDnsHandler {
|
||||||
|
domainPattern: string;
|
||||||
|
recordTypes: string[];
|
||||||
|
handler: (question: plugins.dnsPacket.Question) => plugins.dnsPacket.Answer | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class DnsServer {
|
||||||
|
private udpServer: plugins.dgram.Socket;
|
||||||
|
private httpsServer: plugins.https.Server;
|
||||||
|
private handlers: IDnsHandler[] = [];
|
||||||
|
|
||||||
|
constructor(private options: IDnsServerOptions) {}
|
||||||
|
|
||||||
|
public registerHandler(
|
||||||
|
domainPattern: string,
|
||||||
|
recordTypes: string[],
|
||||||
|
handler: (question: plugins.dnsPacket.Question) => plugins.dnsPacket.Answer | null
|
||||||
|
): void {
|
||||||
|
this.handlers.push({ domainPattern, recordTypes, handler });
|
||||||
|
}
|
||||||
|
|
||||||
|
private processDnsRequest(request: plugins.dnsPacket.Packet): plugins.dnsPacket.Packet {
|
||||||
|
const response: plugins.dnsPacket.Packet = {
|
||||||
|
type: 'response',
|
||||||
|
id: request.id,
|
||||||
|
flags: plugins.dnsPacket.RECURSION_DESIRED | plugins.dnsPacket.RECURSION_AVAILABLE,
|
||||||
|
questions: request.questions,
|
||||||
|
answers: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const question of request.questions) {
|
||||||
|
console.log(`Query for ${question.name} of type ${question.type}`);
|
||||||
|
|
||||||
|
let answered = false;
|
||||||
|
|
||||||
|
for (const handlerEntry of this.handlers) {
|
||||||
|
if (
|
||||||
|
plugins.minimatch.minimatch(question.name, handlerEntry.domainPattern) &&
|
||||||
|
handlerEntry.recordTypes.includes(question.type)
|
||||||
|
) {
|
||||||
|
const answer = handlerEntry.handler(question);
|
||||||
|
if (answer) {
|
||||||
|
response.answers.push(answer);
|
||||||
|
answered = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!answered) {
|
||||||
|
console.log(`No handler found for ${question.name} of type ${question.type}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
private handleHttpsRequest(req: plugins.http.IncomingMessage, res: plugins.http.ServerResponse): void {
|
||||||
|
if (req.method === 'POST' && req.url === '/dns-query') {
|
||||||
|
let body: Buffer[] = [];
|
||||||
|
|
||||||
|
req.on('data', chunk => {
|
||||||
|
body.push(chunk);
|
||||||
|
}).on('end', () => {
|
||||||
|
const msg = Buffer.concat(body);
|
||||||
|
const request = plugins.dnsPacket.decode(msg);
|
||||||
|
const response = this.processDnsRequest(request);
|
||||||
|
const responseData = plugins.dnsPacket.encode(response);
|
||||||
|
res.writeHead(200, { 'Content-Type': 'application/dns-message' });
|
||||||
|
res.end(responseData);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
res.writeHead(404);
|
||||||
|
res.end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async start(): Promise<void> {
|
||||||
|
this.httpsServer = plugins.https.createServer(
|
||||||
|
{
|
||||||
|
key: this.options.httpsKey,
|
||||||
|
cert: this.options.httpsCert,
|
||||||
|
},
|
||||||
|
this.handleHttpsRequest.bind(this)
|
||||||
|
);
|
||||||
|
|
||||||
|
this.udpServer = plugins.dgram.createSocket('udp4');
|
||||||
|
this.udpServer.on('message', (msg, rinfo) => {
|
||||||
|
const request = plugins.dnsPacket.decode(msg);
|
||||||
|
const response = this.processDnsRequest(request);
|
||||||
|
const responseData = plugins.dnsPacket.encode(response);
|
||||||
|
this.udpServer.send(responseData, rinfo.port, rinfo.address);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.udpServer.on('error', (err) => {
|
||||||
|
console.error(`UDP Server error:\n${err.stack}`);
|
||||||
|
this.udpServer.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
const udpListeningDeferred = plugins.smartpromise.defer<void>();
|
||||||
|
const httpsListeningDeferred = plugins.smartpromise.defer<void>();
|
||||||
|
try {
|
||||||
|
this.udpServer.bind(this.options.udpPort, '0.0.0.0', () => {
|
||||||
|
console.log(`UDP DNS server running on port ${this.options.udpPort}`);
|
||||||
|
udpListeningDeferred.resolve();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.httpsServer.listen(this.options.httpsPort, () => {
|
||||||
|
console.log(`HTTPS DNS server running on port ${this.options.httpsPort}`);
|
||||||
|
httpsListeningDeferred.resolve();
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error starting DNS server:', err);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
await Promise.all([udpListeningDeferred.promise, httpsListeningDeferred.promise]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async stop(): Promise<void> {
|
||||||
|
const doneUdp = plugins.smartpromise.defer<void>();
|
||||||
|
const doneHttps = plugins.smartpromise.defer<void>();
|
||||||
|
this.udpServer.close(() => {
|
||||||
|
console.log('UDP DNS server stopped');
|
||||||
|
this.udpServer.unref();
|
||||||
|
this.udpServer = null;
|
||||||
|
doneUdp.resolve();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.httpsServer.close(() => {
|
||||||
|
console.log('HTTPS DNS server stopped');
|
||||||
|
this.httpsServer.unref();
|
||||||
|
this.httpsServer = null;
|
||||||
|
doneHttps.resolve();
|
||||||
|
});
|
||||||
|
|
||||||
|
await Promise.all([doneUdp.promise, doneHttps.promise]);
|
||||||
|
}
|
||||||
|
}
|
172
ts_server/classes.dnstools.ts
Normal file
172
ts_server/classes.dnstools.ts
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
// Import necessary plugins from plugins.ts
|
||||||
|
import * as plugins from './plugins.js';
|
||||||
|
|
||||||
|
interface DnssecZone {
|
||||||
|
zone: string;
|
||||||
|
algorithm: 'ECDSA' | 'ED25519' | 'RSA';
|
||||||
|
keySize: number;
|
||||||
|
days: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DnssecKeyPair {
|
||||||
|
privateKey: string;
|
||||||
|
publicKey: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class DnsSec {
|
||||||
|
private zone: DnssecZone;
|
||||||
|
private keyPair: DnssecKeyPair;
|
||||||
|
private ec?: plugins.elliptic.ec; // For ECDSA algorithms
|
||||||
|
private eddsa?: plugins.elliptic.eddsa; // For EdDSA algorithms
|
||||||
|
|
||||||
|
constructor(zone: DnssecZone) {
|
||||||
|
this.zone = zone;
|
||||||
|
|
||||||
|
// Initialize the appropriate cryptographic instance based on the algorithm
|
||||||
|
switch (this.zone.algorithm) {
|
||||||
|
case 'ECDSA':
|
||||||
|
this.ec = new plugins.elliptic.ec('p256'); // Use P-256 curve for ECDSA
|
||||||
|
break;
|
||||||
|
case 'ED25519':
|
||||||
|
this.eddsa = new plugins.elliptic.eddsa('ed25519');
|
||||||
|
break;
|
||||||
|
case 'RSA':
|
||||||
|
// RSA implementation would go here
|
||||||
|
throw new Error('RSA algorithm is not yet implemented.');
|
||||||
|
default:
|
||||||
|
throw new Error(`Unsupported algorithm: ${this.zone.algorithm}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate the key pair
|
||||||
|
this.keyPair = this.generateKeyPair();
|
||||||
|
}
|
||||||
|
|
||||||
|
private generateKeyPair(): DnssecKeyPair {
|
||||||
|
let privateKey: string;
|
||||||
|
let publicKey: string;
|
||||||
|
|
||||||
|
switch (this.zone.algorithm) {
|
||||||
|
case 'ECDSA':
|
||||||
|
if (!this.ec) throw new Error('EC instance is not initialized.');
|
||||||
|
const ecKeyPair = this.ec.genKeyPair();
|
||||||
|
privateKey = ecKeyPair.getPrivate('hex');
|
||||||
|
publicKey = ecKeyPair.getPublic(false, 'hex'); // Uncompressed format
|
||||||
|
break;
|
||||||
|
case 'ED25519':
|
||||||
|
if (!this.eddsa) throw new Error('EdDSA instance is not initialized.');
|
||||||
|
const secret = plugins.crypto.randomBytes(32);
|
||||||
|
const edKeyPair = this.eddsa.keyFromSecret(secret);
|
||||||
|
privateKey = edKeyPair.getSecret('hex');
|
||||||
|
publicKey = edKeyPair.getPublic('hex');
|
||||||
|
break;
|
||||||
|
case 'RSA':
|
||||||
|
// RSA key generation would be implemented here
|
||||||
|
throw new Error('RSA key generation is not yet implemented.');
|
||||||
|
default:
|
||||||
|
throw new Error(`Unsupported algorithm: ${this.zone.algorithm}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return { privateKey, publicKey };
|
||||||
|
}
|
||||||
|
|
||||||
|
private getAlgorithmNumber(): number {
|
||||||
|
switch (this.zone.algorithm) {
|
||||||
|
case 'ECDSA':
|
||||||
|
return 13; // ECDSAP256SHA256
|
||||||
|
case 'ED25519':
|
||||||
|
return 15;
|
||||||
|
case 'RSA':
|
||||||
|
return 8; // RSASHA256
|
||||||
|
default:
|
||||||
|
throw new Error(`Unsupported algorithm: ${this.zone.algorithm}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public signData(data: Buffer): Buffer {
|
||||||
|
// Sign the data using the private key
|
||||||
|
const keyPair = this.ec!.keyFromPrivate(this.keyPair.privateKey, 'hex');
|
||||||
|
const signature = keyPair.sign(plugins.crypto.createHash('sha256').update(data).digest());
|
||||||
|
return Buffer.from(signature.toDER());
|
||||||
|
}
|
||||||
|
|
||||||
|
private generateDNSKEY(): Buffer {
|
||||||
|
const flags = 256; // 256 indicates a Zone Signing Key (ZSK)
|
||||||
|
const protocol = 3; // Must be 3 according to RFC
|
||||||
|
const algorithm = this.getAlgorithmNumber();
|
||||||
|
|
||||||
|
let publicKeyData: Buffer;
|
||||||
|
|
||||||
|
switch (this.zone.algorithm) {
|
||||||
|
case 'ECDSA':
|
||||||
|
if (!this.ec) throw new Error('EC instance is not initialized.');
|
||||||
|
const ecPublicKey = this.ec.keyFromPublic(this.keyPair.publicKey, 'hex').getPublic();
|
||||||
|
const x = ecPublicKey.getX().toArrayLike(Buffer, 'be', 32);
|
||||||
|
const y = ecPublicKey.getY().toArrayLike(Buffer, 'be', 32);
|
||||||
|
publicKeyData = Buffer.concat([x, y]);
|
||||||
|
break;
|
||||||
|
case 'ED25519':
|
||||||
|
publicKeyData = Buffer.from(this.keyPair.publicKey, 'hex');
|
||||||
|
break;
|
||||||
|
case 'RSA':
|
||||||
|
// RSA public key extraction would go here
|
||||||
|
throw new Error('RSA public key extraction is not yet implemented.');
|
||||||
|
default:
|
||||||
|
throw new Error(`Unsupported algorithm: ${this.zone.algorithm}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct the DNSKEY RDATA
|
||||||
|
const dnskeyRdata = Buffer.concat([
|
||||||
|
Buffer.from([flags >> 8, flags & 0xff]), // Flags (2 bytes)
|
||||||
|
Buffer.from([protocol]), // Protocol (1 byte)
|
||||||
|
Buffer.from([algorithm]), // Algorithm (1 byte)
|
||||||
|
publicKeyData, // Public Key
|
||||||
|
]);
|
||||||
|
|
||||||
|
return dnskeyRdata;
|
||||||
|
}
|
||||||
|
|
||||||
|
private computeKeyTag(dnskeyRdata: Buffer): number {
|
||||||
|
// Key Tag calculation as per RFC 4034, Appendix B
|
||||||
|
let acc = 0;
|
||||||
|
for (let i = 0; i < dnskeyRdata.length; i++) {
|
||||||
|
acc += i & 1 ? dnskeyRdata[i] : dnskeyRdata[i] << 8;
|
||||||
|
}
|
||||||
|
acc += (acc >> 16) & 0xffff;
|
||||||
|
return acc & 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
private getDNSKEYRecord(): string {
|
||||||
|
const dnskeyRdata = this.generateDNSKEY();
|
||||||
|
const flags = 256;
|
||||||
|
const protocol = 3;
|
||||||
|
const algorithm = this.getAlgorithmNumber();
|
||||||
|
const publicKeyData = dnskeyRdata.slice(4); // Skip flags, protocol, algorithm bytes
|
||||||
|
const publicKeyBase64 = publicKeyData.toString('base64');
|
||||||
|
|
||||||
|
return `${this.zone.zone}. IN DNSKEY ${flags} ${protocol} ${algorithm} ${publicKeyBase64}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getDSRecord(): string {
|
||||||
|
const dnskeyRdata = this.generateDNSKEY();
|
||||||
|
const keyTag = this.computeKeyTag(dnskeyRdata);
|
||||||
|
const algorithm = this.getAlgorithmNumber();
|
||||||
|
const digestType = 2; // SHA-256
|
||||||
|
const digest = plugins.crypto
|
||||||
|
.createHash('sha256')
|
||||||
|
.update(dnskeyRdata)
|
||||||
|
.digest('hex')
|
||||||
|
.toUpperCase();
|
||||||
|
|
||||||
|
return `${this.zone.zone}. IN DS ${keyTag} ${algorithm} ${digestType} ${digest}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getKeyPair(): DnssecKeyPair {
|
||||||
|
return this.keyPair;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getDsAndKeyPair(): { keyPair: DnssecKeyPair; dsRecord: string; dnskeyRecord: string } {
|
||||||
|
const dsRecord = this.getDSRecord();
|
||||||
|
const dnskeyRecord = this.getDNSKEYRecord();
|
||||||
|
return { keyPair: this.keyPair, dsRecord, dnskeyRecord };
|
||||||
|
}
|
||||||
|
}
|
1
ts_server/index.ts
Normal file
1
ts_server/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './classes.dnsserver.js';
|
32
ts_server/plugins.ts
Normal file
32
ts_server/plugins.ts
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
// node native
|
||||||
|
import crypto from 'crypto';
|
||||||
|
import fs from 'fs';
|
||||||
|
import http from 'http';
|
||||||
|
import https from 'https';
|
||||||
|
import dgram from 'dgram';
|
||||||
|
|
||||||
|
export {
|
||||||
|
crypto,
|
||||||
|
fs,
|
||||||
|
http,
|
||||||
|
https,
|
||||||
|
dgram,
|
||||||
|
}
|
||||||
|
|
||||||
|
// @push.rocks scope
|
||||||
|
import * as smartpromise from '@push.rocks/smartpromise';
|
||||||
|
|
||||||
|
export {
|
||||||
|
smartpromise,
|
||||||
|
}
|
||||||
|
|
||||||
|
// third party
|
||||||
|
import * as elliptic from 'elliptic';
|
||||||
|
import * as dnsPacket from 'dns-packet';
|
||||||
|
import * as minimatch from 'minimatch';
|
||||||
|
|
||||||
|
export {
|
||||||
|
dnsPacket,
|
||||||
|
elliptic,
|
||||||
|
minimatch,
|
||||||
|
}
|
14
tsconfig.json
Normal file
14
tsconfig.json
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"useDefineForClassFields": false,
|
||||||
|
"target": "ES2022",
|
||||||
|
"module": "NodeNext",
|
||||||
|
"moduleResolution": "NodeNext",
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"verbatimModuleSyntax": true
|
||||||
|
},
|
||||||
|
"exclude": [
|
||||||
|
"dist_*/**/*.d.ts"
|
||||||
|
]
|
||||||
|
}
|
@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": "tslint-config-standard"
|
|
||||||
}
|
|
490
yarn.lock
490
yarn.lock
@ -1,490 +0,0 @@
|
|||||||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
|
||||||
# yarn lockfile v1
|
|
||||||
|
|
||||||
|
|
||||||
"@types/chai-as-promised@0.0.29":
|
|
||||||
version "0.0.29"
|
|
||||||
resolved "https://registry.yarnpkg.com/@types/chai-as-promised/-/chai-as-promised-0.0.29.tgz#43d52892aa998e185a3de3e2477edb8573be1d77"
|
|
||||||
dependencies:
|
|
||||||
"@types/chai" "*"
|
|
||||||
"@types/promises-a-plus" "*"
|
|
||||||
|
|
||||||
"@types/chai-string@^1.1.30":
|
|
||||||
version "1.1.30"
|
|
||||||
resolved "https://registry.yarnpkg.com/@types/chai-string/-/chai-string-1.1.30.tgz#4d8744b31a5a2295fc01c981ed1e2d4c8a070f0a"
|
|
||||||
dependencies:
|
|
||||||
"@types/chai" "*"
|
|
||||||
|
|
||||||
"@types/chai@*":
|
|
||||||
version "4.0.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.0.1.tgz#37fea779617cfec3fd2b19a0247e8bbdd5133bf6"
|
|
||||||
|
|
||||||
"@types/chai@^3.4.35":
|
|
||||||
version "3.5.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/@types/chai/-/chai-3.5.2.tgz#c11cd2817d3a401b7ba0f5a420f35c56139b1c1e"
|
|
||||||
|
|
||||||
"@types/lodash@^4.14.55":
|
|
||||||
version "4.14.69"
|
|
||||||
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.69.tgz#2bbd48c1565e02506f48ed8d1e8e53ea493fd0e6"
|
|
||||||
|
|
||||||
"@types/node@*":
|
|
||||||
version "8.0.14"
|
|
||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.14.tgz#4a19dc6bb61d16c01cbadc7b30ac23518fff176b"
|
|
||||||
|
|
||||||
"@types/promises-a-plus@*":
|
|
||||||
version "0.0.27"
|
|
||||||
resolved "https://registry.yarnpkg.com/@types/promises-a-plus/-/promises-a-plus-0.0.27.tgz#c64651134614c84b8f5d7114ce8901d36a609780"
|
|
||||||
|
|
||||||
"@types/shelljs@^0.7.2":
|
|
||||||
version "0.7.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/@types/shelljs/-/shelljs-0.7.2.tgz#c2bdb3fe80cd7a3da08750ca898ae44c589671f3"
|
|
||||||
dependencies:
|
|
||||||
"@types/node" "*"
|
|
||||||
|
|
||||||
"@types/which@^1.0.28":
|
|
||||||
version "1.0.28"
|
|
||||||
resolved "https://registry.yarnpkg.com/@types/which/-/which-1.0.28.tgz#016e387629b8817bed653fe32eab5d11279c8df6"
|
|
||||||
|
|
||||||
ansi-256-colors@^1.1.0:
|
|
||||||
version "1.1.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/ansi-256-colors/-/ansi-256-colors-1.1.0.tgz#910de50efcc7c09e3d82f2f87abd6b700c18818a"
|
|
||||||
|
|
||||||
ansi-regex@^2.0.0:
|
|
||||||
version "2.1.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
|
|
||||||
|
|
||||||
ansi-styles@^2.2.1:
|
|
||||||
version "2.2.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
|
|
||||||
|
|
||||||
assertion-error@^1.0.1:
|
|
||||||
version "1.0.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.0.2.tgz#13ca515d86206da0bac66e834dd397d87581094c"
|
|
||||||
|
|
||||||
balanced-match@^1.0.0:
|
|
||||||
version "1.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
|
|
||||||
|
|
||||||
beautycolor@^1.0.7:
|
|
||||||
version "1.0.7"
|
|
||||||
resolved "https://registry.yarnpkg.com/beautycolor/-/beautycolor-1.0.7.tgz#a4715738ac4c8221371e9cbeb5a6cc6d11ecbf7c"
|
|
||||||
dependencies:
|
|
||||||
ansi-256-colors "^1.1.0"
|
|
||||||
typings-global "^1.0.14"
|
|
||||||
|
|
||||||
beautylog@^6.1.10:
|
|
||||||
version "6.1.10"
|
|
||||||
resolved "https://registry.yarnpkg.com/beautylog/-/beautylog-6.1.10.tgz#9c27e566937684cb689f9372d98cfa5415d50b72"
|
|
||||||
dependencies:
|
|
||||||
"@types/lodash" "^4.14.55"
|
|
||||||
beautycolor "^1.0.7"
|
|
||||||
figlet "^1.2.0"
|
|
||||||
lodash "^4.17.4"
|
|
||||||
ora "^1.1.0"
|
|
||||||
smartenv "^2.0.0"
|
|
||||||
smartq "^1.1.1"
|
|
||||||
typings-global "^1.0.14"
|
|
||||||
|
|
||||||
bindings@^1.2.1:
|
|
||||||
version "1.2.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.2.1.tgz#14ad6113812d2d37d72e67b4cacb4bb726505f11"
|
|
||||||
|
|
||||||
brace-expansion@^1.1.7:
|
|
||||||
version "1.1.8"
|
|
||||||
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292"
|
|
||||||
dependencies:
|
|
||||||
balanced-match "^1.0.0"
|
|
||||||
concat-map "0.0.1"
|
|
||||||
|
|
||||||
chai-as-promised@^6.0.0:
|
|
||||||
version "6.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/chai-as-promised/-/chai-as-promised-6.0.0.tgz#1a02a433a6f24dafac63b9c96fa1684db1aa8da6"
|
|
||||||
dependencies:
|
|
||||||
check-error "^1.0.2"
|
|
||||||
|
|
||||||
chai-string@^1.3.0:
|
|
||||||
version "1.4.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/chai-string/-/chai-string-1.4.0.tgz#359140c051d36a4e4b1a5fc6b910152f438a8d49"
|
|
||||||
|
|
||||||
chai@^3.5.0:
|
|
||||||
version "3.5.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/chai/-/chai-3.5.0.tgz#4d02637b067fe958bdbfdd3a40ec56fef7373247"
|
|
||||||
dependencies:
|
|
||||||
assertion-error "^1.0.1"
|
|
||||||
deep-eql "^0.1.3"
|
|
||||||
type-detect "^1.0.0"
|
|
||||||
|
|
||||||
chalk@^1.0.0, chalk@^1.1.1:
|
|
||||||
version "1.1.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
|
|
||||||
dependencies:
|
|
||||||
ansi-styles "^2.2.1"
|
|
||||||
escape-string-regexp "^1.0.2"
|
|
||||||
has-ansi "^2.0.0"
|
|
||||||
strip-ansi "^3.0.0"
|
|
||||||
supports-color "^2.0.0"
|
|
||||||
|
|
||||||
check-error@^1.0.2:
|
|
||||||
version "1.0.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82"
|
|
||||||
|
|
||||||
cli-cursor@^2.1.0:
|
|
||||||
version "2.1.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5"
|
|
||||||
dependencies:
|
|
||||||
restore-cursor "^2.0.0"
|
|
||||||
|
|
||||||
cli-spinners@^1.0.0:
|
|
||||||
version "1.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-1.0.0.tgz#ef987ed3d48391ac3dab9180b406a742180d6e6a"
|
|
||||||
|
|
||||||
concat-map@0.0.1:
|
|
||||||
version "0.0.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
|
||||||
|
|
||||||
deep-eql@^0.1.3:
|
|
||||||
version "0.1.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-0.1.3.tgz#ef558acab8de25206cd713906d74e56930eb69f2"
|
|
||||||
dependencies:
|
|
||||||
type-detect "0.1.1"
|
|
||||||
|
|
||||||
define-properties@^1.1.2:
|
|
||||||
version "1.1.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.2.tgz#83a73f2fea569898fb737193c8f873caf6d45c94"
|
|
||||||
dependencies:
|
|
||||||
foreach "^2.0.5"
|
|
||||||
object-keys "^1.0.8"
|
|
||||||
|
|
||||||
early@^2.1.1:
|
|
||||||
version "2.1.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/early/-/early-2.1.1.tgz#841e23254ea5dc54d8afaeee82f5ab65c00ee23c"
|
|
||||||
dependencies:
|
|
||||||
beautycolor "^1.0.7"
|
|
||||||
smartq "^1.1.1"
|
|
||||||
typings-global "^1.0.16"
|
|
||||||
|
|
||||||
es-abstract@^1.5.1:
|
|
||||||
version "1.7.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.7.0.tgz#dfade774e01bfcd97f96180298c449c8623fb94c"
|
|
||||||
dependencies:
|
|
||||||
es-to-primitive "^1.1.1"
|
|
||||||
function-bind "^1.1.0"
|
|
||||||
is-callable "^1.1.3"
|
|
||||||
is-regex "^1.0.3"
|
|
||||||
|
|
||||||
es-to-primitive@^1.1.1:
|
|
||||||
version "1.1.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.1.1.tgz#45355248a88979034b6792e19bb81f2b7975dd0d"
|
|
||||||
dependencies:
|
|
||||||
is-callable "^1.1.1"
|
|
||||||
is-date-object "^1.0.1"
|
|
||||||
is-symbol "^1.0.1"
|
|
||||||
|
|
||||||
es6-error@^4.0.2:
|
|
||||||
version "4.0.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.0.2.tgz#eec5c726eacef51b7f6b73c20db6e1b13b069c98"
|
|
||||||
|
|
||||||
escape-string-regexp@^1.0.2:
|
|
||||||
version "1.0.5"
|
|
||||||
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
|
|
||||||
|
|
||||||
figlet@^1.2.0:
|
|
||||||
version "1.2.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/figlet/-/figlet-1.2.0.tgz#6c46537378fab649146b5a6143dda019b430b410"
|
|
||||||
|
|
||||||
foreach@^2.0.5:
|
|
||||||
version "2.0.5"
|
|
||||||
resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99"
|
|
||||||
|
|
||||||
fs.realpath@^1.0.0:
|
|
||||||
version "1.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
|
|
||||||
|
|
||||||
function-bind@^1.0.2, function-bind@^1.1.0:
|
|
||||||
version "1.1.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.0.tgz#16176714c801798e4e8f2cf7f7529467bb4a5771"
|
|
||||||
|
|
||||||
glob@^7.0.0:
|
|
||||||
version "7.1.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
|
|
||||||
dependencies:
|
|
||||||
fs.realpath "^1.0.0"
|
|
||||||
inflight "^1.0.4"
|
|
||||||
inherits "2"
|
|
||||||
minimatch "^3.0.4"
|
|
||||||
once "^1.3.0"
|
|
||||||
path-is-absolute "^1.0.0"
|
|
||||||
|
|
||||||
has-ansi@^2.0.0:
|
|
||||||
version "2.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91"
|
|
||||||
dependencies:
|
|
||||||
ansi-regex "^2.0.0"
|
|
||||||
|
|
||||||
has@^1.0.1:
|
|
||||||
version "1.0.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/has/-/has-1.0.1.tgz#8461733f538b0837c9361e39a9ab9e9704dc2f28"
|
|
||||||
dependencies:
|
|
||||||
function-bind "^1.0.2"
|
|
||||||
|
|
||||||
inflight@^1.0.4:
|
|
||||||
version "1.0.6"
|
|
||||||
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
|
|
||||||
dependencies:
|
|
||||||
once "^1.3.0"
|
|
||||||
wrappy "1"
|
|
||||||
|
|
||||||
inherits@2:
|
|
||||||
version "2.0.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
|
|
||||||
|
|
||||||
interpret@^1.0.0:
|
|
||||||
version "1.0.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.0.3.tgz#cbc35c62eeee73f19ab7b10a801511401afc0f90"
|
|
||||||
|
|
||||||
is-callable@^1.1.1, is-callable@^1.1.3:
|
|
||||||
version "1.1.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.3.tgz#86eb75392805ddc33af71c92a0eedf74ee7604b2"
|
|
||||||
|
|
||||||
is-date-object@^1.0.1:
|
|
||||||
version "1.0.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16"
|
|
||||||
|
|
||||||
is-regex@^1.0.3:
|
|
||||||
version "1.0.4"
|
|
||||||
resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491"
|
|
||||||
dependencies:
|
|
||||||
has "^1.0.1"
|
|
||||||
|
|
||||||
is-symbol@^1.0.1:
|
|
||||||
version "1.0.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.1.tgz#3cc59f00025194b6ab2e38dbae6689256b660572"
|
|
||||||
|
|
||||||
isexe@^2.0.0:
|
|
||||||
version "2.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
|
|
||||||
|
|
||||||
leakage@^0.3.0:
|
|
||||||
version "0.3.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/leakage/-/leakage-0.3.0.tgz#15d698abdc76bbc6439601f4f3020e77e2d50c39"
|
|
||||||
dependencies:
|
|
||||||
es6-error "^4.0.2"
|
|
||||||
left-pad "^1.1.3"
|
|
||||||
memwatch-next "^0.3.0"
|
|
||||||
minimist "^1.2.0"
|
|
||||||
pretty-bytes "^4.0.2"
|
|
||||||
|
|
||||||
left-pad@^1.1.3:
|
|
||||||
version "1.1.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/left-pad/-/left-pad-1.1.3.tgz#612f61c033f3a9e08e939f1caebeea41b6f3199a"
|
|
||||||
|
|
||||||
lodash@^4.17.4:
|
|
||||||
version "4.17.4"
|
|
||||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
|
|
||||||
|
|
||||||
log-symbols@^1.0.2:
|
|
||||||
version "1.0.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-1.0.2.tgz#376ff7b58ea3086a0f09facc74617eca501e1a18"
|
|
||||||
dependencies:
|
|
||||||
chalk "^1.0.0"
|
|
||||||
|
|
||||||
memwatch-next@^0.3.0:
|
|
||||||
version "0.3.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/memwatch-next/-/memwatch-next-0.3.0.tgz#2111050f9a906e0aa2d72a4ec0f0089c78726f8f"
|
|
||||||
dependencies:
|
|
||||||
bindings "^1.2.1"
|
|
||||||
nan "^2.3.2"
|
|
||||||
|
|
||||||
mimic-fn@^1.0.0:
|
|
||||||
version "1.1.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.1.0.tgz#e667783d92e89dbd342818b5230b9d62a672ad18"
|
|
||||||
|
|
||||||
minimatch@^3.0.4:
|
|
||||||
version "3.0.4"
|
|
||||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
|
|
||||||
dependencies:
|
|
||||||
brace-expansion "^1.1.7"
|
|
||||||
|
|
||||||
minimist@^1.2.0:
|
|
||||||
version "1.2.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
|
|
||||||
|
|
||||||
nan@^2.3.2:
|
|
||||||
version "2.6.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.6.2.tgz#e4ff34e6c95fdfb5aecc08de6596f43605a7db45"
|
|
||||||
|
|
||||||
object-keys@^1.0.8:
|
|
||||||
version "1.0.11"
|
|
||||||
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.11.tgz#c54601778ad560f1142ce0e01bcca8b56d13426d"
|
|
||||||
|
|
||||||
object.getownpropertydescriptors@^2.0.3:
|
|
||||||
version "2.0.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16"
|
|
||||||
dependencies:
|
|
||||||
define-properties "^1.1.2"
|
|
||||||
es-abstract "^1.5.1"
|
|
||||||
|
|
||||||
once@^1.3.0:
|
|
||||||
version "1.4.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
|
|
||||||
dependencies:
|
|
||||||
wrappy "1"
|
|
||||||
|
|
||||||
onetime@^2.0.0:
|
|
||||||
version "2.0.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4"
|
|
||||||
dependencies:
|
|
||||||
mimic-fn "^1.0.0"
|
|
||||||
|
|
||||||
ora@^1.1.0:
|
|
||||||
version "1.3.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/ora/-/ora-1.3.0.tgz#80078dd2b92a934af66a3ad72a5b910694ede51a"
|
|
||||||
dependencies:
|
|
||||||
chalk "^1.1.1"
|
|
||||||
cli-cursor "^2.1.0"
|
|
||||||
cli-spinners "^1.0.0"
|
|
||||||
log-symbols "^1.0.2"
|
|
||||||
|
|
||||||
path-is-absolute@^1.0.0:
|
|
||||||
version "1.0.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
|
|
||||||
|
|
||||||
path-parse@^1.0.5:
|
|
||||||
version "1.0.5"
|
|
||||||
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1"
|
|
||||||
|
|
||||||
pretty-bytes@^4.0.2:
|
|
||||||
version "4.0.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-4.0.2.tgz#b2bf82e7350d65c6c33aa95aaa5a4f6327f61cd9"
|
|
||||||
|
|
||||||
rechoir@^0.6.2:
|
|
||||||
version "0.6.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384"
|
|
||||||
dependencies:
|
|
||||||
resolve "^1.1.6"
|
|
||||||
|
|
||||||
resolve@^1.1.6:
|
|
||||||
version "1.3.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.3.3.tgz#655907c3469a8680dc2de3a275a8fdd69691f0e5"
|
|
||||||
dependencies:
|
|
||||||
path-parse "^1.0.5"
|
|
||||||
|
|
||||||
restore-cursor@^2.0.0:
|
|
||||||
version "2.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf"
|
|
||||||
dependencies:
|
|
||||||
onetime "^2.0.0"
|
|
||||||
signal-exit "^3.0.2"
|
|
||||||
|
|
||||||
semver@^5.3.0:
|
|
||||||
version "5.3.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f"
|
|
||||||
|
|
||||||
shelljs@^0.7.8:
|
|
||||||
version "0.7.8"
|
|
||||||
resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.8.tgz#decbcf874b0d1e5fb72e14b164a9683048e9acb3"
|
|
||||||
dependencies:
|
|
||||||
glob "^7.0.0"
|
|
||||||
interpret "^1.0.0"
|
|
||||||
rechoir "^0.6.2"
|
|
||||||
|
|
||||||
signal-exit@^3.0.2:
|
|
||||||
version "3.0.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
|
|
||||||
|
|
||||||
smartchai@^1.0.3:
|
|
||||||
version "1.0.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/smartchai/-/smartchai-1.0.3.tgz#de6d010bb8b5aef24cb70b31a5f5334e8c41b72f"
|
|
||||||
dependencies:
|
|
||||||
"@types/chai" "^3.4.35"
|
|
||||||
"@types/chai-as-promised" "0.0.29"
|
|
||||||
"@types/chai-string" "^1.1.30"
|
|
||||||
chai "^3.5.0"
|
|
||||||
chai-as-promised "^6.0.0"
|
|
||||||
chai-string "^1.3.0"
|
|
||||||
|
|
||||||
smartdelay@^1.0.3:
|
|
||||||
version "1.0.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/smartdelay/-/smartdelay-1.0.3.tgz#5fd44dad77262d110702f0293efa80c072cfb579"
|
|
||||||
dependencies:
|
|
||||||
smartq "^1.1.1"
|
|
||||||
typings-global "^1.0.16"
|
|
||||||
|
|
||||||
smartenv@^2.0.0:
|
|
||||||
version "2.0.6"
|
|
||||||
resolved "https://registry.yarnpkg.com/smartenv/-/smartenv-2.0.6.tgz#b38c679b0c151b9af548f68c3a072c29d1417e8d"
|
|
||||||
dependencies:
|
|
||||||
lodash "^4.17.4"
|
|
||||||
smartq "^1.1.1"
|
|
||||||
typings-global "^1.0.14"
|
|
||||||
|
|
||||||
smartq@^1.1.1, smartq@^1.1.6:
|
|
||||||
version "1.1.6"
|
|
||||||
resolved "https://registry.yarnpkg.com/smartq/-/smartq-1.1.6.tgz#0c1ff4336d95e95b4f1fdd8ccd7e2c5a323b8412"
|
|
||||||
dependencies:
|
|
||||||
typings-global "^1.0.19"
|
|
||||||
util.promisify "^1.0.0"
|
|
||||||
|
|
||||||
smartshell@^1.0.6:
|
|
||||||
version "1.0.12"
|
|
||||||
resolved "https://registry.yarnpkg.com/smartshell/-/smartshell-1.0.12.tgz#dcd4b55b1699d54257af682f58a887b1a6cf08b8"
|
|
||||||
dependencies:
|
|
||||||
"@types/shelljs" "^0.7.2"
|
|
||||||
"@types/which" "^1.0.28"
|
|
||||||
shelljs "^0.7.8"
|
|
||||||
smartq "^1.1.6"
|
|
||||||
typings-global "^1.0.19"
|
|
||||||
which "^1.2.14"
|
|
||||||
|
|
||||||
strip-ansi@^3.0.0:
|
|
||||||
version "3.0.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
|
|
||||||
dependencies:
|
|
||||||
ansi-regex "^2.0.0"
|
|
||||||
|
|
||||||
supports-color@^2.0.0:
|
|
||||||
version "2.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
|
|
||||||
|
|
||||||
tapbundle@^1.1.1:
|
|
||||||
version "1.1.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/tapbundle/-/tapbundle-1.1.1.tgz#ec4172c0e82a77b1f6133fef2606311ede28a62d"
|
|
||||||
dependencies:
|
|
||||||
early "^2.1.1"
|
|
||||||
leakage "^0.3.0"
|
|
||||||
smartchai "^1.0.3"
|
|
||||||
smartdelay "^1.0.3"
|
|
||||||
smartq "^1.1.1"
|
|
||||||
typings-global "^1.0.19"
|
|
||||||
|
|
||||||
type-detect@0.1.1:
|
|
||||||
version "0.1.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-0.1.1.tgz#0ba5ec2a885640e470ea4e8505971900dac58822"
|
|
||||||
|
|
||||||
type-detect@^1.0.0:
|
|
||||||
version "1.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-1.0.0.tgz#762217cc06db258ec48908a1298e8b95121e8ea2"
|
|
||||||
|
|
||||||
typings-global@^1.0.14, typings-global@^1.0.16, typings-global@^1.0.19:
|
|
||||||
version "1.0.19"
|
|
||||||
resolved "https://registry.yarnpkg.com/typings-global/-/typings-global-1.0.19.tgz#3376a72d4de1e5541bf5702248ff64c3e6ea316c"
|
|
||||||
dependencies:
|
|
||||||
semver "^5.3.0"
|
|
||||||
smartshell "^1.0.6"
|
|
||||||
|
|
||||||
util.promisify@^1.0.0:
|
|
||||||
version "1.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.0.tgz#440f7165a459c9a16dc145eb8e72f35687097030"
|
|
||||||
dependencies:
|
|
||||||
define-properties "^1.1.2"
|
|
||||||
object.getownpropertydescriptors "^2.0.3"
|
|
||||||
|
|
||||||
which@^1.2.14:
|
|
||||||
version "1.2.14"
|
|
||||||
resolved "https://registry.yarnpkg.com/which/-/which-1.2.14.tgz#9a87c4378f03e827cecaf1acdf56c736c01c14e5"
|
|
||||||
dependencies:
|
|
||||||
isexe "^2.0.0"
|
|
||||||
|
|
||||||
wrappy@1:
|
|
||||||
version "1.0.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
|
|
Reference in New Issue
Block a user