mirror of
https://github.com/YuzuZensai/Cloudflare-DDNS-Updater.git
synced 2026-07-15 14:26:39 +00:00
🎨 style: add Prettier formatting
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
node_modules
|
||||
dist
|
||||
configs
|
||||
coverage
|
||||
bun.lock
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"printWidth": 100,
|
||||
"singleQuote": false,
|
||||
"trailingComma": "all"
|
||||
}
|
||||
@@ -5,15 +5,16 @@
|
||||
"": {
|
||||
"name": "cloudflare-ddns-updater",
|
||||
"dependencies": {
|
||||
"axios": "latest",
|
||||
"dotenv": "latest",
|
||||
"validator": "latest",
|
||||
"winston": "latest",
|
||||
"axios": "^1.18.1",
|
||||
"dotenv": "^17.4.2",
|
||||
"validator": "^13.15.35",
|
||||
"winston": "3.19.0",
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "latest",
|
||||
"@types/validator": "latest",
|
||||
"typescript": "latest",
|
||||
"@types/node": "^26.0.1",
|
||||
"@types/validator": "^13.15.10",
|
||||
"prettier": "^3.9.4",
|
||||
"typescript": "^6.0.3",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -110,6 +111,8 @@
|
||||
|
||||
"one-time": ["one-time@1.0.0", "", { "dependencies": { "fn.name": "1.x.x" } }, "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g=="],
|
||||
|
||||
"prettier": ["prettier@3.9.4", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-yWG/o/4oJfo036EKAfK6ACAoDOfHeRHx4tuxkfBZiauURiaSmYwlpOr5LQqKtIkRD2z1PLteme2WoxEnj4tHTg=="],
|
||||
|
||||
"proxy-from-env": ["proxy-from-env@2.1.0", "", {}, "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA=="],
|
||||
|
||||
"readable-stream": ["readable-stream@3.6.0", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA=="],
|
||||
|
||||
@@ -1,46 +1,46 @@
|
||||
[
|
||||
{
|
||||
"token": "{ENV_TOKEN:EXAMPLE_SITE_TOKEN}",
|
||||
"updateInterval": 60,
|
||||
"zone": [
|
||||
{
|
||||
"id": "zone-id-1",
|
||||
"type": "A",
|
||||
"name": "example.com",
|
||||
"content": "{CURRENT_IPv4}",
|
||||
"ttl": 1,
|
||||
"proxied": false
|
||||
},
|
||||
{
|
||||
"id": "zone-id-2",
|
||||
"type": "AAAA",
|
||||
"name": "another.example.com",
|
||||
"content": "{CURRENT_IPv6}",
|
||||
"ttl": 1,
|
||||
"proxied": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"token": "hard-code-cloudflare-token-2",
|
||||
"updateInterval": 60,
|
||||
"zone": [
|
||||
{
|
||||
"id": "zone-id-1",
|
||||
"type": "A",
|
||||
"name": "example.com",
|
||||
"content": "{CURRENT_IPv4}",
|
||||
"ttl": 1,
|
||||
"proxied": false
|
||||
},
|
||||
{
|
||||
"id": "zone-id-2",
|
||||
"type": "A",
|
||||
"name": "another.example.com",
|
||||
"content": "{CURRENT_IPv6}",
|
||||
"ttl": 1,
|
||||
"proxied": false
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
{
|
||||
"token": "{ENV_TOKEN:EXAMPLE_SITE_TOKEN}",
|
||||
"updateInterval": 60,
|
||||
"zone": [
|
||||
{
|
||||
"id": "zone-id-1",
|
||||
"type": "A",
|
||||
"name": "example.com",
|
||||
"content": "{CURRENT_IPv4}",
|
||||
"ttl": 1,
|
||||
"proxied": false
|
||||
},
|
||||
{
|
||||
"id": "zone-id-2",
|
||||
"type": "AAAA",
|
||||
"name": "another.example.com",
|
||||
"content": "{CURRENT_IPv6}",
|
||||
"ttl": 1,
|
||||
"proxied": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"token": "hard-code-cloudflare-token-2",
|
||||
"updateInterval": 60,
|
||||
"zone": [
|
||||
{
|
||||
"id": "zone-id-1",
|
||||
"type": "A",
|
||||
"name": "example.com",
|
||||
"content": "{CURRENT_IPv4}",
|
||||
"ttl": 1,
|
||||
"proxied": false
|
||||
},
|
||||
{
|
||||
"id": "zone-id-2",
|
||||
"type": "A",
|
||||
"name": "another.example.com",
|
||||
"content": "{CURRENT_IPv6}",
|
||||
"ttl": 1,
|
||||
"proxied": false
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
@@ -15,10 +15,13 @@
|
||||
"devDependencies": {
|
||||
"@types/node": "^26.0.1",
|
||||
"@types/validator": "^13.15.10",
|
||||
"prettier": "^3.9.4",
|
||||
"typescript": "^6.0.3"
|
||||
},
|
||||
"scripts": {
|
||||
"typecheck": "tsc --noEmit",
|
||||
"format": "prettier --write .",
|
||||
"format:check": "prettier --check .",
|
||||
"dev": "bun --watch src/index.ts",
|
||||
"start": "bun src/index.ts",
|
||||
"build": "bun run typecheck",
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
import App from './providers/App';
|
||||
import App from "./providers/App";
|
||||
|
||||
App.loadConfig();
|
||||
App.loadENV();
|
||||
App.loadDaemon();
|
||||
|
||||
export default App;
|
||||
export default App;
|
||||
|
||||
+39
-41
@@ -1,64 +1,62 @@
|
||||
import winston from 'winston';
|
||||
import winston from "winston";
|
||||
|
||||
const levels = {
|
||||
critical: 0,
|
||||
error: 1,
|
||||
alert: 2,
|
||||
warn: 3,
|
||||
info: 4,
|
||||
http: 5,
|
||||
debug: 6,
|
||||
critical: 0,
|
||||
error: 1,
|
||||
alert: 2,
|
||||
warn: 3,
|
||||
info: 4,
|
||||
http: 5,
|
||||
debug: 6,
|
||||
};
|
||||
|
||||
const level = () => {
|
||||
const env = process.env.NODE_ENV || 'development';
|
||||
const isDevelopment = env === 'development';
|
||||
return isDevelopment ? 'debug' : 'info';
|
||||
const env = process.env.NODE_ENV || "development";
|
||||
const isDevelopment = env === "development";
|
||||
return isDevelopment ? "debug" : "info";
|
||||
};
|
||||
|
||||
const colors = {
|
||||
critical: 'red',
|
||||
error: 'red',
|
||||
alert: 'red',
|
||||
warn: 'yellow',
|
||||
info: 'green',
|
||||
http: 'magenta',
|
||||
debug: 'white',
|
||||
critical: "red",
|
||||
error: "red",
|
||||
alert: "red",
|
||||
warn: "yellow",
|
||||
info: "green",
|
||||
http: "magenta",
|
||||
debug: "white",
|
||||
};
|
||||
|
||||
winston.addColors(colors);
|
||||
|
||||
const consoleFormat = winston.format.combine(
|
||||
winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss:ms' }),
|
||||
winston.format.colorize({ all: true }),
|
||||
winston.format.printf(
|
||||
(info) => `[${info.timestamp}] [${info.level}] ${info.message}`
|
||||
)
|
||||
winston.format.timestamp({ format: "YYYY-MM-DD HH:mm:ss:ms" }),
|
||||
winston.format.colorize({ all: true }),
|
||||
winston.format.printf((info) => `[${info.timestamp}] [${info.level}] ${info.message}`),
|
||||
);
|
||||
|
||||
const format = winston.format.combine(
|
||||
winston.format.timestamp({
|
||||
format: new Date().toISOString()
|
||||
}),
|
||||
winston.format.json()
|
||||
)
|
||||
winston.format.timestamp({
|
||||
format: new Date().toISOString(),
|
||||
}),
|
||||
winston.format.json(),
|
||||
);
|
||||
|
||||
const transports = [
|
||||
new winston.transports.Console({
|
||||
format: consoleFormat
|
||||
}),
|
||||
new winston.transports.File({
|
||||
filename: 'logs/error.log',
|
||||
level: 'error',
|
||||
}),
|
||||
new winston.transports.File({ filename: 'logs/all.log' }),
|
||||
new winston.transports.Console({
|
||||
format: consoleFormat,
|
||||
}),
|
||||
new winston.transports.File({
|
||||
filename: "logs/error.log",
|
||||
level: "error",
|
||||
}),
|
||||
new winston.transports.File({ filename: "logs/all.log" }),
|
||||
];
|
||||
|
||||
const Logger = winston.createLogger({
|
||||
level: level(),
|
||||
levels,
|
||||
format,
|
||||
transports,
|
||||
level: level(),
|
||||
levels,
|
||||
format,
|
||||
transports,
|
||||
});
|
||||
|
||||
export default Logger;
|
||||
export default Logger;
|
||||
|
||||
+17
-17
@@ -1,23 +1,23 @@
|
||||
import Logger from '../libs/Logger';
|
||||
import Logger from "../libs/Logger";
|
||||
|
||||
import Environment from './Environment';
|
||||
import Configuration from './Configuration';
|
||||
import Daemon from './Daemon';
|
||||
import Environment from "./Environment";
|
||||
import Configuration from "./Configuration";
|
||||
import Daemon from "./Daemon";
|
||||
|
||||
class App {
|
||||
public loadConfig(): void {
|
||||
Logger.log('info', 'Loading configuration');
|
||||
Configuration.init();
|
||||
}
|
||||
public loadConfig(): void {
|
||||
Logger.log("info", "Loading configuration");
|
||||
Configuration.init();
|
||||
}
|
||||
|
||||
public loadENV(): void {
|
||||
Logger.log('info', 'Loading environment');
|
||||
Environment.init();
|
||||
}
|
||||
public loadDaemon() : void {
|
||||
Logger.log('info', 'Loading daemon');
|
||||
Daemon.init();
|
||||
}
|
||||
public loadENV(): void {
|
||||
Logger.log("info", "Loading environment");
|
||||
Environment.init();
|
||||
}
|
||||
public loadDaemon(): void {
|
||||
Logger.log("info", "Loading daemon");
|
||||
Daemon.init();
|
||||
}
|
||||
}
|
||||
|
||||
export default new App;
|
||||
export default new App();
|
||||
|
||||
@@ -3,44 +3,42 @@ import path from "path";
|
||||
|
||||
const ConfigurationData: any = [];
|
||||
class Configuration {
|
||||
|
||||
public init(): void {
|
||||
const dir = path.join(process.cwd(), 'configs/');
|
||||
if (!fs.existsSync(dir)) {
|
||||
fs.mkdirSync(dir);
|
||||
}
|
||||
this.copyExampleIfNotExists("UpdaterConfig.json");
|
||||
|
||||
this.loadConfig("UpdaterConfig.json");
|
||||
public init(): void {
|
||||
const dir = path.join(process.cwd(), "configs/");
|
||||
if (!fs.existsSync(dir)) {
|
||||
fs.mkdirSync(dir);
|
||||
}
|
||||
this.copyExampleIfNotExists("UpdaterConfig.json");
|
||||
|
||||
public loadConfig(configFileName: string): void {
|
||||
const dir = path.join(process.cwd(), 'configs/');
|
||||
if (!fs.existsSync(path.join(dir, configFileName)))
|
||||
throw new Error(`Config file ${configFileName} does not exist`);
|
||||
this.loadConfig("UpdaterConfig.json");
|
||||
}
|
||||
|
||||
const config = JSON.parse(fs.readFileSync(path.join(dir, configFileName)).toString());
|
||||
ConfigurationData[configFileName.replace(/\.[^/.]+$/, "")] = config;
|
||||
public loadConfig(configFileName: string): void {
|
||||
const dir = path.join(process.cwd(), "configs/");
|
||||
if (!fs.existsSync(path.join(dir, configFileName)))
|
||||
throw new Error(`Config file ${configFileName} does not exist`);
|
||||
|
||||
const config = JSON.parse(fs.readFileSync(path.join(dir, configFileName)).toString());
|
||||
ConfigurationData[configFileName.replace(/\.[^/.]+$/, "")] = config;
|
||||
}
|
||||
|
||||
public getConfig(key?: string) {
|
||||
if (!key) return ConfigurationData;
|
||||
else {
|
||||
if (ConfigurationData[key]) return ConfigurationData[key];
|
||||
else throw new Error(`No configuration found for ${key}`);
|
||||
}
|
||||
}
|
||||
|
||||
public getConfig(key?: string) {
|
||||
if(!key)
|
||||
return ConfigurationData;
|
||||
else {
|
||||
if(ConfigurationData[key])
|
||||
return ConfigurationData[key];
|
||||
else
|
||||
throw new Error(`No configuration found for ${key}`);
|
||||
}
|
||||
private copyExampleIfNotExists(file: string): void {
|
||||
const dir = path.join(process.cwd(), "configs/");
|
||||
if (!fs.existsSync(path.join(dir, file))) {
|
||||
fs.copyFileSync(
|
||||
path.join(process.cwd(), "configs_example/", `${file.replace(".json", ".example.json")}`),
|
||||
path.join(dir, file),
|
||||
);
|
||||
}
|
||||
|
||||
private copyExampleIfNotExists(file: string): void {
|
||||
const dir = path.join(process.cwd(), 'configs/');
|
||||
if (!fs.existsSync(path.join(dir, file))) {
|
||||
fs.copyFileSync(path.join(process.cwd(), 'configs_example/', `${file.replace('.json', '.example.json')}`), path.join(dir, file));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
export default new Configuration();
|
||||
|
||||
+348
-295
@@ -3,353 +3,406 @@ import Environment from "./Environment";
|
||||
import Configuration from "./Configuration";
|
||||
|
||||
import axios from "axios";
|
||||
import validator from 'validator';
|
||||
import validator from "validator";
|
||||
|
||||
interface CloudflareConfig {
|
||||
token: string,
|
||||
updateInterval: number,
|
||||
zone: Array<ZoneConfig>
|
||||
token: string;
|
||||
updateInterval: number;
|
||||
zone: Array<ZoneConfig>;
|
||||
}
|
||||
|
||||
interface ZoneConfig {
|
||||
id: string,
|
||||
type: string,
|
||||
name: string,
|
||||
content: string,
|
||||
ttl: number,
|
||||
proxied: boolean
|
||||
id: string;
|
||||
type: string;
|
||||
name: string;
|
||||
content: string;
|
||||
ttl: number;
|
||||
proxied: boolean;
|
||||
}
|
||||
|
||||
class Deamon {
|
||||
private config: Array<CloudflareConfig> = [];
|
||||
|
||||
private config: Array<CloudflareConfig> = [];
|
||||
constructor() {}
|
||||
|
||||
constructor () {
|
||||
public init(): void {
|
||||
const _config = Configuration.getConfig("UpdaterConfig");
|
||||
if (!_config) {
|
||||
Logger.error("No configuration found");
|
||||
return;
|
||||
}
|
||||
|
||||
public init(): void {
|
||||
const _config = Configuration.getConfig("UpdaterConfig");
|
||||
if(!_config) {
|
||||
Logger.error('No configuration found')
|
||||
return;
|
||||
}
|
||||
|
||||
for(let cloudflareConfig of _config) {
|
||||
if(!this.isCloudflareConfig(cloudflareConfig)) {
|
||||
Logger.error(`Invalid configuration for cloudflare: ${JSON.stringify(cloudflareConfig)}`);
|
||||
continue;
|
||||
}
|
||||
for (let cloudflareConfig of _config) {
|
||||
if (!this.isCloudflareConfig(cloudflareConfig)) {
|
||||
Logger.error(`Invalid configuration for cloudflare: ${JSON.stringify(cloudflareConfig)}`);
|
||||
continue;
|
||||
}
|
||||
|
||||
this.config.push(cloudflareConfig);
|
||||
}
|
||||
|
||||
Logger.info(`Loaded ${this.config.length} cloudflare configs`);
|
||||
this.start();
|
||||
this.config.push(cloudflareConfig);
|
||||
}
|
||||
|
||||
public start(): void {
|
||||
Logger.info('Starting deamon');
|
||||
for(const cloudflareConfig of this.config) {
|
||||
this.update(cloudflareConfig);
|
||||
setInterval(() => this.update(cloudflareConfig), cloudflareConfig.updateInterval * 1000);
|
||||
}
|
||||
Logger.info(`Loaded ${this.config.length} cloudflare configs`);
|
||||
this.start();
|
||||
}
|
||||
|
||||
public start(): void {
|
||||
Logger.info("Starting deamon");
|
||||
for (const cloudflareConfig of this.config) {
|
||||
this.update(cloudflareConfig);
|
||||
setInterval(() => this.update(cloudflareConfig), cloudflareConfig.updateInterval * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
private async update(cloudflareConfig: CloudflareConfig) {
|
||||
let token = cloudflareConfig.token;
|
||||
|
||||
// Replace placeholders env with value
|
||||
if (this.isEnviromentTokenPlaceholder(token)) {
|
||||
const envTokenName = this.parseEnvironmentTokenPlaceholderName(token)!;
|
||||
if (process.env[envTokenName]) {
|
||||
token = process.env[envTokenName]!;
|
||||
} else {
|
||||
Logger.error(`Environment variable ${envTokenName} not found`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private async update(cloudflareConfig: CloudflareConfig) {
|
||||
let IPv4, IPv6;
|
||||
try {
|
||||
IPv4 = await this.getCurrentIPv4();
|
||||
IPv6 = await this.getCurrentIPv6();
|
||||
} catch (err) {
|
||||
Logger.error(`Unable to fetch ip address: ${err}`);
|
||||
return;
|
||||
}
|
||||
|
||||
let token = cloudflareConfig.token;
|
||||
IPv4 && Logger.info(`Current IPv4 address: ${IPv4}`);
|
||||
IPv6 && Logger.info(`Current IPv6 address: ${IPv6}`);
|
||||
|
||||
// Replace placeholders env with value
|
||||
if(this.isEnviromentTokenPlaceholder(token)) {
|
||||
const envTokenName = this.parseEnvironmentTokenPlaceholderName(token)!;
|
||||
if(process.env[envTokenName]) {
|
||||
token = process.env[envTokenName]!;
|
||||
}
|
||||
else {
|
||||
Logger.error(`Environment variable ${envTokenName} not found`);
|
||||
return;
|
||||
}
|
||||
for (const zone of cloudflareConfig.zone) {
|
||||
const api = new CloudflareAPI(token, zone.id);
|
||||
const records = await api
|
||||
.getRecord({
|
||||
type: zone.type,
|
||||
name: zone.name,
|
||||
})
|
||||
.catch((err) => {
|
||||
Logger.error(`Unable to get records for zone ${zone.id}`);
|
||||
return err;
|
||||
});
|
||||
|
||||
if (records instanceof Error) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// No records found, create it
|
||||
if (!records || records.length === 0) {
|
||||
const newContent = zone.content
|
||||
.replaceAll("{CURRENT_IPv4}", IPv4)
|
||||
.replaceAll("{CURRENT_IPv6}", IPv6);
|
||||
|
||||
const result = await api
|
||||
.createRecord({
|
||||
type: zone.type,
|
||||
name: zone.name,
|
||||
content: IPv4,
|
||||
ttl: zone.ttl,
|
||||
proxied: zone.proxied,
|
||||
})
|
||||
.catch((err) => {
|
||||
Logger.error(`Unable to create record: ${err.message}`);
|
||||
return err;
|
||||
});
|
||||
|
||||
if (records instanceof Error) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let IPv4, IPv6;
|
||||
try {
|
||||
IPv4 = await this.getCurrentIPv4();
|
||||
IPv6 = await this.getCurrentIPv6();
|
||||
} catch(err) {
|
||||
Logger.error(`Unable to fetch ip address: ${err}`);
|
||||
return;
|
||||
}
|
||||
if (result) Logger.info(`Created [${zone.type}] (${zone.name} -> ${newContent})`);
|
||||
}
|
||||
|
||||
IPv4 && Logger.info(`Current IPv4 address: ${IPv4}`);
|
||||
IPv6 && Logger.info(`Current IPv6 address: ${IPv6}`);
|
||||
|
||||
for(const zone of cloudflareConfig.zone) {
|
||||
const api = new CloudflareAPI(token, zone.id);
|
||||
const records = await api.getRecord({
|
||||
type: zone.type,
|
||||
name: zone.name
|
||||
}).catch(err => {
|
||||
Logger.error(`Unable to get records for zone ${zone.id}`);
|
||||
return err;
|
||||
// Only 1 matching records found
|
||||
else if (records.length === 1) {
|
||||
const record = records[0];
|
||||
const newContent = zone.content
|
||||
.replaceAll("{CURRENT_IPv4}", IPv4)
|
||||
.replaceAll("{CURRENT_IPv6}", IPv6);
|
||||
|
||||
// Check if the ip is the same
|
||||
if (record.content !== IPv4 && record.content !== IPv6) {
|
||||
const updateResult = await api
|
||||
.updateRecord({
|
||||
record_id: record.id,
|
||||
type: zone.type,
|
||||
name: zone.name,
|
||||
ttl: zone.ttl,
|
||||
content: newContent,
|
||||
proxied: zone.proxied,
|
||||
})
|
||||
.catch((err) => {
|
||||
Logger.error(`Unable to update record: ${err.message}`);
|
||||
return err;
|
||||
});
|
||||
|
||||
if(records instanceof Error) {
|
||||
continue;
|
||||
}
|
||||
if (records instanceof Error) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// No records found, create it
|
||||
if(!records || records.length === 0) {
|
||||
const newContent = zone.content.replaceAll("{CURRENT_IPv4}", IPv4).replaceAll("{CURRENT_IPv6}", IPv6);
|
||||
|
||||
const result = await api.createRecord({
|
||||
type: zone.type,
|
||||
name: zone.name,
|
||||
content: IPv4,
|
||||
ttl: zone.ttl,
|
||||
proxied: zone.proxied
|
||||
}).catch(err => {
|
||||
Logger.error(`Unable to create record: ${err.message}`);
|
||||
return err;
|
||||
});
|
||||
|
||||
if(records instanceof Error) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(result)
|
||||
Logger.info(`Created [${zone.type}] (${zone.name} -> ${newContent})`);
|
||||
}
|
||||
|
||||
// Only 1 matching records found
|
||||
else if(records.length === 1) {
|
||||
const record = records[0];
|
||||
const newContent = zone.content.replaceAll("{CURRENT_IPv4}", IPv4).replaceAll("{CURRENT_IPv6}", IPv6);
|
||||
|
||||
// Check if the ip is the same
|
||||
if(record.content !== IPv4 && record.content !== IPv6) {
|
||||
const updateResult = await api.updateRecord({
|
||||
record_id: record.id,
|
||||
type: zone.type,
|
||||
name: zone.name,
|
||||
ttl: zone.ttl,
|
||||
content: newContent,
|
||||
proxied: zone.proxied
|
||||
}).catch(err => {
|
||||
Logger.error(`Unable to update record: ${err.message}`);
|
||||
return err;
|
||||
});
|
||||
|
||||
if(records instanceof Error) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(updateResult)
|
||||
Logger.info(`[${zone.type}] (${zone.name} -> ${record.content}) updated to (${zone.name} -> ${newContent})`);
|
||||
}
|
||||
else if(
|
||||
record.ttl !== zone.ttl ||
|
||||
record.proxied !== zone.proxied
|
||||
) {
|
||||
const updateResult = await api.updateRecord({
|
||||
record_id: record.id,
|
||||
type: zone.type,
|
||||
name: zone.name,
|
||||
ttl: zone.ttl,
|
||||
content: newContent,
|
||||
proxied: zone.proxied
|
||||
}).catch(err => {
|
||||
Logger.error(`Unable to update record: ${err.message}`);
|
||||
console.log(err);
|
||||
return;
|
||||
});
|
||||
|
||||
if(updateResult)
|
||||
Logger.info(`[${zone.type}] (${zone.name} -> ${record.content}) updated proxy status/ttl (TTL: ${record.ttl} -> ${zone.ttl}) (Proxy status: ${record.proxied} -> ${zone.proxied})`);
|
||||
}
|
||||
|
||||
else {
|
||||
Logger.info(`[${zone.type}] (${zone.name} -> ${record.content}) already up to date`);
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Many records found
|
||||
else if(records.length > 1) {
|
||||
Logger.error(`Multiple records found for ${zone.type} (${zone.name}) (Multiple records are not supported right now)`);
|
||||
continue;
|
||||
}
|
||||
if (updateResult)
|
||||
Logger.info(
|
||||
`[${zone.type}] (${zone.name} -> ${record.content}) updated to (${zone.name} -> ${newContent})`,
|
||||
);
|
||||
} else if (record.ttl !== zone.ttl || record.proxied !== zone.proxied) {
|
||||
const updateResult = await api
|
||||
.updateRecord({
|
||||
record_id: record.id,
|
||||
type: zone.type,
|
||||
name: zone.name,
|
||||
ttl: zone.ttl,
|
||||
content: newContent,
|
||||
proxied: zone.proxied,
|
||||
})
|
||||
.catch((err) => {
|
||||
Logger.error(`Unable to update record: ${err.message}`);
|
||||
console.log(err);
|
||||
return;
|
||||
});
|
||||
|
||||
if (updateResult)
|
||||
Logger.info(
|
||||
`[${zone.type}] (${zone.name} -> ${record.content}) updated proxy status/ttl (TTL: ${record.ttl} -> ${zone.ttl}) (Proxy status: ${record.proxied} -> ${zone.proxied})`,
|
||||
);
|
||||
} else {
|
||||
Logger.info(`[${zone.type}] (${zone.name} -> ${record.content}) already up to date`);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Many records found
|
||||
else if (records.length > 1) {
|
||||
Logger.error(
|
||||
`Multiple records found for ${zone.type} (${zone.name}) (Multiple records are not supported right now)`,
|
||||
);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private isCloudflareConfig(object: any): object is CloudflareConfig {
|
||||
if (!this.arraysEqual(Object.keys(object), ["token", "updateInterval", "zone"])) return false;
|
||||
|
||||
const res =
|
||||
object &&
|
||||
object.token &&
|
||||
typeof object.token == "string" &&
|
||||
object.updateInterval &&
|
||||
typeof object.updateInterval == "number";
|
||||
|
||||
for (let zone of object.zone) {
|
||||
if (!this.isZoneConfig(zone)) return false;
|
||||
}
|
||||
|
||||
private isCloudflareConfig(object: any): object is CloudflareConfig {
|
||||
|
||||
if(!this.arraysEqual(Object.keys(object), ['token', 'updateInterval', 'zone']))
|
||||
return false;
|
||||
if (!res) return false;
|
||||
|
||||
const res = object &&
|
||||
object.token && typeof(object.token) == 'string' &&
|
||||
object.updateInterval && typeof(object.updateInterval) == 'number';
|
||||
const token = object.token as string;
|
||||
|
||||
for(let zone of object.zone) {
|
||||
if(!this.isZoneConfig(zone))
|
||||
return false;
|
||||
}
|
||||
// Process the env token
|
||||
if (this.isEnviromentTokenPlaceholder(token)) {
|
||||
const envTokenName = this.parseEnvironmentTokenPlaceholderName(token)!;
|
||||
const envValue = process.env[envTokenName];
|
||||
|
||||
if(!res) return false;
|
||||
|
||||
const token = object.token as string;
|
||||
|
||||
// Process the env token
|
||||
if(this.isEnviromentTokenPlaceholder(token)) {
|
||||
const envTokenName = this.parseEnvironmentTokenPlaceholderName(token)!;
|
||||
const envValue = process.env[envTokenName];
|
||||
|
||||
if(!envValue) {
|
||||
Logger.error(`Environment variable ${envTokenName} not found`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
if (!envValue) {
|
||||
Logger.error(`Environment variable ${envTokenName} not found`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private isZoneConfig(object: any): object is ZoneConfig {
|
||||
|
||||
if(!this.arraysEqual(Object.keys(object), ['id', 'type', 'name', 'content', 'ttl', 'proxied']))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
private isZoneConfig(object: any): object is ZoneConfig {
|
||||
if (!this.arraysEqual(Object.keys(object), ["id", "type", "name", "content", "ttl", "proxied"]))
|
||||
return false;
|
||||
|
||||
const res = object &&
|
||||
object.id && typeof(object.id) == 'string' &&
|
||||
object.type && typeof(object.type) == 'string' &&
|
||||
object.name && typeof(object.name) == 'string' &&
|
||||
object.content && typeof(object.content) == 'string' &&
|
||||
object.ttl && typeof(object.ttl) == 'number' &&
|
||||
typeof(object.proxied) == 'boolean';
|
||||
const res =
|
||||
object &&
|
||||
object.id &&
|
||||
typeof object.id == "string" &&
|
||||
object.type &&
|
||||
typeof object.type == "string" &&
|
||||
object.name &&
|
||||
typeof object.name == "string" &&
|
||||
object.content &&
|
||||
typeof object.content == "string" &&
|
||||
object.ttl &&
|
||||
typeof object.ttl == "number" &&
|
||||
typeof object.proxied == "boolean";
|
||||
|
||||
if(!res) return false;
|
||||
if (!res) return false;
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
private isEnviromentTokenPlaceholder(token: string) {
|
||||
return token.startsWith("{ENV_TOKEN:") && token.endsWith("}");
|
||||
}
|
||||
|
||||
private parseEnvironmentTokenPlaceholderName(token: string) {
|
||||
if (!this.isEnviromentTokenPlaceholder(token)) return null;
|
||||
return token.split("{ENV_TOKEN:")[1].slice(0, -1);
|
||||
}
|
||||
|
||||
private async getCurrentIPv4() {
|
||||
const response = await axios.get("https://api.ipify.org?format=json");
|
||||
|
||||
if (!response.data.ip) throw new Error("Unable to fetch ip address");
|
||||
|
||||
if (!validator.isIP(response.data.ip, 4)) throw new Error("Invalid IP");
|
||||
|
||||
return response.data.ip;
|
||||
}
|
||||
|
||||
private async getCurrentIPv6() {
|
||||
const response = await axios.get("https://api64.ipify.org/?format=json");
|
||||
|
||||
if (!response.data.ip) throw new Error("Unable to fetch ip address");
|
||||
|
||||
if (!validator.isIP(response.data.ip, 6)) return null;
|
||||
|
||||
return response.data.ip;
|
||||
}
|
||||
|
||||
private arraysEqual(a: any, b: any) {
|
||||
if (a === b) return true;
|
||||
if (a == null || b == null) return false;
|
||||
if (a.length !== b.length) return false;
|
||||
|
||||
for (var i = 0; i < a.length; ++i) {
|
||||
if (a[i] !== b[i]) return false;
|
||||
}
|
||||
|
||||
private isEnviromentTokenPlaceholder(token: string) {
|
||||
return token.startsWith('{ENV_TOKEN:') && token.endsWith('}');
|
||||
}
|
||||
|
||||
private parseEnvironmentTokenPlaceholderName(token: string) {
|
||||
if(!this.isEnviromentTokenPlaceholder(token)) return null;
|
||||
return token.split('{ENV_TOKEN:')[1].slice(0, -1);
|
||||
}
|
||||
|
||||
private async getCurrentIPv4() {
|
||||
const response = await axios.get("https://api.ipify.org?format=json");
|
||||
|
||||
if(!response.data.ip)
|
||||
throw new Error("Unable to fetch ip address");
|
||||
|
||||
if(!validator.isIP(response.data.ip, 4))
|
||||
throw new Error("Invalid IP");
|
||||
|
||||
return response.data.ip;
|
||||
}
|
||||
|
||||
private async getCurrentIPv6() {
|
||||
const response = await axios.get("https://api64.ipify.org/?format=json");
|
||||
|
||||
if(!response.data.ip)
|
||||
throw new Error("Unable to fetch ip address");
|
||||
|
||||
if(!validator.isIP(response.data.ip, 6))
|
||||
return null;
|
||||
|
||||
return response.data.ip;
|
||||
}
|
||||
|
||||
private arraysEqual(a: any, b: any) {
|
||||
if (a === b) return true;
|
||||
if (a == null || b == null) return false;
|
||||
if (a.length !== b.length) return false;
|
||||
|
||||
for (var i = 0; i < a.length; ++i) {
|
||||
if (a[i] !== b[i]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class CloudflareAPI {
|
||||
private token: string;
|
||||
private zoneId: string;
|
||||
private token: string;
|
||||
private zoneId: string;
|
||||
|
||||
constructor(token: string, zoneId: string) {
|
||||
this.token = token;
|
||||
this.zoneId = zoneId;
|
||||
}
|
||||
constructor(token: string, zoneId: string) {
|
||||
this.token = token;
|
||||
this.zoneId = zoneId;
|
||||
}
|
||||
|
||||
public async getRecord({ name, type, content, proxied, page }: { name?: string, type?: string, content?: string, proxied?: boolean, page?: number }) {
|
||||
const response = await axios.get(`https://api.cloudflare.com/client/v4/zones/${this.zoneId}/dns_records`, {
|
||||
params: {
|
||||
name,
|
||||
type,
|
||||
perPage: 5000,
|
||||
content,
|
||||
proxied,
|
||||
page
|
||||
},
|
||||
headers: {
|
||||
'Authorization': `Bearer ${this.token}`,
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
});
|
||||
public async getRecord({
|
||||
name,
|
||||
type,
|
||||
content,
|
||||
proxied,
|
||||
page,
|
||||
}: {
|
||||
name?: string;
|
||||
type?: string;
|
||||
content?: string;
|
||||
proxied?: boolean;
|
||||
page?: number;
|
||||
}) {
|
||||
const response = await axios.get(
|
||||
`https://api.cloudflare.com/client/v4/zones/${this.zoneId}/dns_records`,
|
||||
{
|
||||
params: {
|
||||
name,
|
||||
type,
|
||||
perPage: 5000,
|
||||
content,
|
||||
proxied,
|
||||
page,
|
||||
},
|
||||
headers: {
|
||||
Authorization: `Bearer ${this.token}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
if(response.data.success !== true)
|
||||
throw new Error(`Unable to fetch record: ${response.data.errors[0].message}`);
|
||||
if (response.data.success !== true)
|
||||
throw new Error(`Unable to fetch record: ${response.data.errors[0].message}`);
|
||||
|
||||
return response.data.result;
|
||||
}
|
||||
return response.data.result;
|
||||
}
|
||||
|
||||
public async createRecord ({ name, type, content, ttl, proxied }: { name?: string, type?: string, content?: string, ttl: number, proxied?: boolean }) {
|
||||
const response = await axios.post(`https://api.cloudflare.com/client/v4/zones/${this.zoneId}/dns_records`, {
|
||||
type,
|
||||
name,
|
||||
content,
|
||||
ttl,
|
||||
proxied
|
||||
}, {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${this.token}`,
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
});
|
||||
public async createRecord({
|
||||
name,
|
||||
type,
|
||||
content,
|
||||
ttl,
|
||||
proxied,
|
||||
}: {
|
||||
name?: string;
|
||||
type?: string;
|
||||
content?: string;
|
||||
ttl: number;
|
||||
proxied?: boolean;
|
||||
}) {
|
||||
const response = await axios.post(
|
||||
`https://api.cloudflare.com/client/v4/zones/${this.zoneId}/dns_records`,
|
||||
{
|
||||
type,
|
||||
name,
|
||||
content,
|
||||
ttl,
|
||||
proxied,
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${this.token}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
if(response.data.success !== true)
|
||||
throw new Error(`Unable to create record: ${response.data.errors[0].message}`);
|
||||
if (response.data.success !== true)
|
||||
throw new Error(`Unable to create record: ${response.data.errors[0].message}`);
|
||||
|
||||
return response.data.result;
|
||||
}
|
||||
return response.data.result;
|
||||
}
|
||||
|
||||
public async updateRecord({ record_id, name, type, content, ttl, proxied }: { record_id: string, name?: string, type?: string, content?: string, ttl: number, proxied?: boolean }) {
|
||||
const response = await axios.put(`https://api.cloudflare.com/client/v4/zones/${this.zoneId}/dns_records/${record_id}`, {
|
||||
type,
|
||||
name,
|
||||
content,
|
||||
ttl,
|
||||
proxied
|
||||
}, {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${this.token}`,
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
});
|
||||
public async updateRecord({
|
||||
record_id,
|
||||
name,
|
||||
type,
|
||||
content,
|
||||
ttl,
|
||||
proxied,
|
||||
}: {
|
||||
record_id: string;
|
||||
name?: string;
|
||||
type?: string;
|
||||
content?: string;
|
||||
ttl: number;
|
||||
proxied?: boolean;
|
||||
}) {
|
||||
const response = await axios.put(
|
||||
`https://api.cloudflare.com/client/v4/zones/${this.zoneId}/dns_records/${record_id}`,
|
||||
{
|
||||
type,
|
||||
name,
|
||||
content,
|
||||
ttl,
|
||||
proxied,
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${this.token}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
if(response.data.success !== true)
|
||||
throw new Error(`Unable to update record: ${response.data.errors[0].message}`);
|
||||
if (response.data.success !== true)
|
||||
throw new Error(`Unable to update record: ${response.data.errors[0].message}`);
|
||||
|
||||
return response.data.result;
|
||||
}
|
||||
return response.data.result;
|
||||
}
|
||||
}
|
||||
|
||||
export default new Deamon();
|
||||
|
||||
@@ -3,49 +3,41 @@ import * as dotenv from "dotenv";
|
||||
|
||||
import Logger from "../libs/Logger";
|
||||
|
||||
const requiredENV = [
|
||||
'NODE_ENV',
|
||||
];
|
||||
const requiredENV = ["NODE_ENV"];
|
||||
|
||||
class Environment {
|
||||
public init(): void {
|
||||
dotenv.config({ path: path.resolve(__dirname, "../../.env") });
|
||||
|
||||
public init(): void {
|
||||
dotenv.config({ path: path.resolve(__dirname, "../../.env") });
|
||||
|
||||
for (let param of requiredENV) {
|
||||
if (this.isUndefinedOrEmpty(process.env[param]))
|
||||
throw new Error(`.env ${param} is undefined`);
|
||||
}
|
||||
|
||||
// NODE_ENV Checks
|
||||
if (this.get().NODE_ENV != "production" && this.get().NODE_ENV != "development")
|
||||
throw new Error('.env NODE_ENV must be either "production" or "development"');
|
||||
|
||||
Logger.log('info', `Running in ${process.env.NODE_ENV} environment`);
|
||||
for (let param of requiredENV) {
|
||||
if (this.isUndefinedOrEmpty(process.env[param]))
|
||||
throw new Error(`.env ${param} is undefined`);
|
||||
}
|
||||
|
||||
public get(): any {
|
||||
// NODE_ENV Checks
|
||||
if (this.get().NODE_ENV != "production" && this.get().NODE_ENV != "development")
|
||||
throw new Error('.env NODE_ENV must be either "production" or "development"');
|
||||
|
||||
const NODE_ENV = process.env.NODE_ENV;
|
||||
|
||||
return {
|
||||
NODE_ENV
|
||||
};
|
||||
}
|
||||
Logger.log("info", `Running in ${process.env.NODE_ENV} environment`);
|
||||
}
|
||||
|
||||
private isUndefinedOrEmpty(value: String | undefined): boolean {
|
||||
if(typeof value === 'undefined')
|
||||
return true;
|
||||
public get(): any {
|
||||
const NODE_ENV = process.env.NODE_ENV;
|
||||
|
||||
if(value === undefined)
|
||||
return true;
|
||||
return {
|
||||
NODE_ENV,
|
||||
};
|
||||
}
|
||||
|
||||
if(value === '')
|
||||
return true;
|
||||
private isUndefinedOrEmpty(value: String | undefined): boolean {
|
||||
if (typeof value === "undefined") return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
if (value === undefined) return true;
|
||||
|
||||
if (value === "") return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export default new Environment();
|
||||
|
||||
+99
-99
@@ -1,108 +1,108 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
/* Visit https://aka.ms/tsconfig.json to read more about this file */
|
||||
"compilerOptions": {
|
||||
/* Visit https://aka.ms/tsconfig.json to read more about this file */
|
||||
|
||||
/* Projects */
|
||||
// "incremental": true, /* Enable incremental compilation */
|
||||
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
|
||||
// "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */
|
||||
// "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */
|
||||
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
|
||||
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
|
||||
/* Projects */
|
||||
// "incremental": true, /* Enable incremental compilation */
|
||||
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
|
||||
// "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */
|
||||
// "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */
|
||||
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
|
||||
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
|
||||
|
||||
/* Language and Environment */
|
||||
"target": "ES2021",
|
||||
/* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
|
||||
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
|
||||
// "jsx": "preserve", /* Specify what JSX code is generated. */
|
||||
// "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
|
||||
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
|
||||
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */
|
||||
// "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
|
||||
// "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */
|
||||
// "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */
|
||||
// "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
|
||||
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
|
||||
/* Language and Environment */
|
||||
"target": "ES2021",
|
||||
/* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
|
||||
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
|
||||
// "jsx": "preserve", /* Specify what JSX code is generated. */
|
||||
// "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
|
||||
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
|
||||
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */
|
||||
// "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
|
||||
// "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */
|
||||
// "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */
|
||||
// "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
|
||||
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
|
||||
|
||||
/* Modules */
|
||||
"module": "commonjs",
|
||||
/* Specify what module code is generated. */
|
||||
// "rootDir": "./", /* Specify the root folder within your source files. */
|
||||
// "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
|
||||
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
|
||||
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
|
||||
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
|
||||
// "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */
|
||||
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
|
||||
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
||||
// "resolveJsonModule": true, /* Enable importing .json files */
|
||||
// "noResolve": true, /* Disallow `import`s, `require`s or `<reference>`s from expanding the number of files TypeScript should add to a project. */
|
||||
/* Modules */
|
||||
"module": "commonjs",
|
||||
/* Specify what module code is generated. */
|
||||
// "rootDir": "./", /* Specify the root folder within your source files. */
|
||||
// "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
|
||||
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
|
||||
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
|
||||
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
|
||||
// "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */
|
||||
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
|
||||
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
||||
// "resolveJsonModule": true, /* Enable importing .json files */
|
||||
// "noResolve": true, /* Disallow `import`s, `require`s or `<reference>`s from expanding the number of files TypeScript should add to a project. */
|
||||
|
||||
/* JavaScript Support */
|
||||
// "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */
|
||||
// "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
|
||||
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */
|
||||
/* JavaScript Support */
|
||||
// "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */
|
||||
// "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
|
||||
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */
|
||||
|
||||
/* Emit */
|
||||
// "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
|
||||
// "declarationMap": true, /* Create sourcemaps for d.ts files. */
|
||||
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
|
||||
"sourceMap": true,
|
||||
/* Create source map files for emitted JavaScript files. */
|
||||
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */
|
||||
"outDir": "dist",
|
||||
/* Specify an output folder for all emitted files. */
|
||||
// "removeComments": true, /* Disable emitting comments. */
|
||||
// "noEmit": true, /* Disable emitting files from a compilation. */
|
||||
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
|
||||
// "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */
|
||||
// "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
|
||||
// "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
|
||||
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
|
||||
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
|
||||
// "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
|
||||
// "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
|
||||
// "newLine": "crlf", /* Set the newline character for emitting files. */
|
||||
// "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */
|
||||
// "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */
|
||||
// "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
|
||||
// "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */
|
||||
// "declarationDir": "./", /* Specify the output directory for generated declaration files. */
|
||||
// "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
|
||||
/* Emit */
|
||||
// "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
|
||||
// "declarationMap": true, /* Create sourcemaps for d.ts files. */
|
||||
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
|
||||
"sourceMap": true,
|
||||
/* Create source map files for emitted JavaScript files. */
|
||||
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */
|
||||
"outDir": "dist",
|
||||
/* Specify an output folder for all emitted files. */
|
||||
// "removeComments": true, /* Disable emitting comments. */
|
||||
// "noEmit": true, /* Disable emitting files from a compilation. */
|
||||
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
|
||||
// "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */
|
||||
// "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
|
||||
// "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
|
||||
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
|
||||
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
|
||||
// "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
|
||||
// "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
|
||||
// "newLine": "crlf", /* Set the newline character for emitting files. */
|
||||
// "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */
|
||||
// "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */
|
||||
// "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
|
||||
// "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */
|
||||
// "declarationDir": "./", /* Specify the output directory for generated declaration files. */
|
||||
// "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
|
||||
|
||||
/* Interop Constraints */
|
||||
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
|
||||
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
|
||||
"esModuleInterop": true,
|
||||
/* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */
|
||||
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
/* Ensure that casing is correct in imports. */
|
||||
/* Interop Constraints */
|
||||
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
|
||||
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
|
||||
"esModuleInterop": true,
|
||||
/* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */
|
||||
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
/* Ensure that casing is correct in imports. */
|
||||
|
||||
/* Type Checking */
|
||||
"strict": true,
|
||||
/* Enable all strict type-checking options. */
|
||||
// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */
|
||||
// "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */
|
||||
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
|
||||
// "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */
|
||||
// "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
|
||||
// "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */
|
||||
// "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */
|
||||
"alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
|
||||
// "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */
|
||||
// "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */
|
||||
// "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
|
||||
// "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
|
||||
// "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
|
||||
// "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */
|
||||
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
|
||||
// "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */
|
||||
// "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
|
||||
// "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
|
||||
/* Type Checking */
|
||||
"strict": true,
|
||||
/* Enable all strict type-checking options. */
|
||||
// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */
|
||||
// "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */
|
||||
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
|
||||
// "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */
|
||||
// "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
|
||||
// "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */
|
||||
// "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */
|
||||
"alwaysStrict": true /* Ensure 'use strict' is always emitted. */,
|
||||
// "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */
|
||||
// "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */
|
||||
// "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
|
||||
// "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
|
||||
// "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
|
||||
// "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */
|
||||
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
|
||||
// "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */
|
||||
// "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
|
||||
// "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
|
||||
|
||||
/* Completeness */
|
||||
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
|
||||
"skipLibCheck": true /* Skip type checking all .d.ts files. */
|
||||
}
|
||||
}
|
||||
/* Completeness */
|
||||
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
|
||||
"skipLibCheck": true /* Skip type checking all .d.ts files. */
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user