diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..9575226 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,5 @@ +* +!src +!tsconfig.json +!package.json +!pnpm-lock.yaml diff --git a/.gitignore b/.gitignore index eec8101..dd303ec 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ .env ip.log - +dist node_modules diff --git a/.sample.env b/.sample.env index 7cc9b7e..c31a7d0 100644 --- a/.sample.env +++ b/.sample.env @@ -1,9 +1,8 @@ # Required -EMAIL=my@mail.com -KEY=my_api_key +TOKEn=myapitoken ZONE=example.org DNS_RECORD=some.example.org # Optional #CRON=* * * * * -#RESOLVER=http://ipv4.icanhazip.com/ \ No newline at end of file +#RESOLVER=http://ipv4.icanhazip.com/ diff --git a/Dockerfile b/Dockerfile index 511d4bc..f9b3e8d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,9 +1,10 @@ -FROM node:14-alpine +FROM node:16-alpine WORKDIR /app -ADD ./package.json yarn.lock ./ -RUN yarn -ADD ./script.js ./ +ADD . . +RUN npm install -g pnpm +RUN pnpm install --frozen-lockfile +RUN pnpm run build -CMD ["node", "script.js"] \ No newline at end of file +CMD ["node", "."] diff --git a/README.md b/README.md index 5f79513..9cb858e 100644 --- a/README.md +++ b/README.md @@ -11,17 +11,18 @@ ## Quickstart 🚀 -1. Get your api token [here](https://dash.cloudflare.com/profile/api-tokens) (Top right -> My Profile -> API Tokens) +1. Get your API Token [here](https://dash.cloudflare.com/profile/api-tokens) (Top right -> My Profile -> API Tokens) Click create token. You can then use the Edit DNS Zone template. Give it a name. -![Settings](https://i.imgur.com/dLs8PHs.png) - 2. Create an `.env` file: ```bash +TOKEN=mytoken +# Or (Legacy mode) EMAIL=my@mail.com -KEY=my_api_key +KEY=Global_API_Key + ZONE=example.org DNS_RECORD=some.example.org ``` @@ -32,12 +33,6 @@ DNS_RECORD=some.example.org docker run -d --name ddns --restart always --env-file .env cupcakearmy/ddns-cloudflare ``` -To check logs: - -```bash -docker logs ddns -``` - ### Docker-Copmose With docker-compose: @@ -49,6 +44,18 @@ cp .sample.env .env docker-compose up -d ``` +## ENV Reference + +| Env | Description | Default | +| ------------ | ------------------------------------------------------ | ---------------------- | +| `EMAIL` | [Legacy] E-Mail of the Cloudflare account. | | +| `KEY` | [Legacy] Key for authentication. | | +| `TOKEN` | API Token that can be used instead of `EMAIL` & `KEY`. | | +| `ZONE` | Cloudflare zone where your domain is. | | +| `DNS_RECORD` | The actual DNS record that should be updated. | | +| `CRON` | Frequency of updates. | \*/5 \* \* \* \* | +| `RESOLVER` | The endpoint used to determine your public ip. | https://api.ipify.org/ | + ## Customize ### Custom CRON diff --git a/docker-compose.yml b/docker-compose.yml index 2ece900..78e4581 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,4 +1,4 @@ -version: '3.7' +version: '3.8' services: ddns: diff --git a/package.json b/package.json index 54ac930..3ccf9c7 100644 --- a/package.json +++ b/package.json @@ -1,14 +1,21 @@ { "license": "MIT", + "main": "dist", "scripts": { - "docker:build": "docker build -t cupcakearmy/ddns-cloudflare:lastest .", - "docker:push": "docker push cupcakearmy/ddns-cloudflare:lastest", - "docker:publish": "yarn run docker:build && yarn run docker:push" + "dev": "tsnd src/index.ts", + "build": "tsc" }, "dependencies": { - "axios": "^0.21.1", + "axios": "^0.23.0", "cloudflare": "^2.7.0", "cron": "^1.8.2", - "dotenv": "^8.2.0" + "dotenv": "^10.0.0", + "winston": "^3.3.3" + }, + "devDependencies": { + "@types/cloudflare": "^2.7.6", + "@types/cron": "^1.7.3", + "ts-node-dev": "^1.1.8", + "typescript": "^4.4.4" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..97afa27 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,764 @@ +lockfileVersion: 5.3 + +specifiers: + '@types/cloudflare': ^2.7.6 + '@types/cron': ^1.7.3 + axios: ^0.23.0 + cloudflare: ^2.7.0 + cron: ^1.8.2 + dotenv: ^10.0.0 + ts-node-dev: ^1.1.8 + typescript: ^4.4.4 + winston: ^3.3.3 + +dependencies: + axios: 0.23.0 + cloudflare: 2.9.1 + cron: 1.8.2 + dotenv: 10.0.0 + winston: 3.3.3 + +devDependencies: + '@types/cloudflare': 2.7.6 + '@types/cron': 1.7.3 + ts-node-dev: 1.1.8_typescript@4.4.4 + typescript: 4.4.4 + +packages: + + /@dabh/diagnostics/2.0.2: + resolution: {integrity: sha512-+A1YivoVDNNVCdfozHSR8v/jyuuLTMXwjWuxPFlFlUapXoGc+Gj9mDlTDDfrwl7rXCl2tNZ0kE8sIBO6YOn96Q==} + dependencies: + colorspace: 1.1.4 + enabled: 2.0.0 + kuler: 2.0.0 + dev: false + + /@types/cloudflare/2.7.6: + resolution: {integrity: sha512-Q2Zo+i3OoGIuNKy5Wti+CAg0dVliBTtVBt5PQacB9tY7VXRg/vA+CatdnylPmNFW5PSW/w5ztUr+hznnVz0OXQ==} + dev: true + + /@types/cron/1.7.3: + resolution: {integrity: sha512-iPmUXyIJG1Js+ldPYhOQcYU3kCAQ2FWrSkm1FJPoii2eYSn6wEW6onPukNTT0bfiflexNSRPl6KWmAIqS+36YA==} + dependencies: + '@types/node': 16.11.3 + moment: 2.29.1 + dev: true + + /@types/node/16.11.3: + resolution: {integrity: sha512-aIYL9Eemcecs1y77XzFGiSc+FdfN58k4J23UEe6+hynf4Wd9g4DzQPwIKL080vSMuubFqy2hWwOzCtJdc6vFKw==} + dev: true + + /@types/strip-bom/3.0.0: + resolution: {integrity: sha1-FKjsOVbC6B7bdSB5CuzyHCkK69I=} + dev: true + + /@types/strip-json-comments/0.0.30: + resolution: {integrity: sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==} + dev: true + + /agent-base/6.0.2: + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} + engines: {node: '>= 6.0.0'} + dependencies: + debug: 4.3.2 + transitivePeerDependencies: + - supports-color + dev: false + + /anymatch/3.1.2: + resolution: {integrity: sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==} + engines: {node: '>= 8'} + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.0 + dev: true + + /arg/4.1.3: + resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} + dev: true + + /async/3.2.1: + resolution: {integrity: sha512-XdD5lRO/87udXCMC9meWdYiR+Nq6ZjUfXidViUZGu2F1MO4T3XwZ1et0hb2++BgLfhyJwy44BGB/yx80ABx8hg==} + dev: false + + /autocreate/1.2.0: + resolution: {integrity: sha1-UiFnmSxBcsFUeeX4jzSGpFKkDLo=} + dev: false + + /axios/0.23.0: + resolution: {integrity: sha512-NmvAE4i0YAv5cKq8zlDoPd1VLKAqX5oLuZKs8xkJa4qi6RGn0uhCYFjWtHHC9EM/MwOwYWOs53W+V0aqEXq1sg==} + dependencies: + follow-redirects: 1.14.4 + transitivePeerDependencies: + - debug + dev: false + + /balanced-match/1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + dev: true + + /binary-extensions/2.2.0: + resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} + engines: {node: '>=8'} + dev: true + + /brace-expansion/1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + dev: true + + /braces/3.0.2: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + engines: {node: '>=8'} + dependencies: + fill-range: 7.0.1 + dev: true + + /buffer-from/1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + dev: true + + /capture-stack-trace/1.0.1: + resolution: {integrity: sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw==} + engines: {node: '>=0.10.0'} + dev: false + + /chokidar/3.5.2: + resolution: {integrity: sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==} + engines: {node: '>= 8.10.0'} + dependencies: + anymatch: 3.1.2 + braces: 3.0.2 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.2 + dev: true + + /cloudflare/2.9.1: + resolution: {integrity: sha512-x8yXPPoloy7xQ9GCKnsvQ3U1nwvcLndA2B3nxwSjIWxgLTUJOyakeEDsrqxZO8Dr6FkGdaXwy554fQVMpOabiw==} + dependencies: + autocreate: 1.2.0 + es-class: 2.1.1 + got: 6.7.1 + https-proxy-agent: 5.0.0 + object-assign: 4.1.1 + should-proxy: 1.0.4 + url-pattern: 1.0.3 + transitivePeerDependencies: + - supports-color + dev: false + + /color-convert/1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + dependencies: + color-name: 1.1.3 + dev: false + + /color-name/1.1.3: + resolution: {integrity: sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=} + dev: false + + /color-name/1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + dev: false + + /color-string/1.6.0: + resolution: {integrity: sha512-c/hGS+kRWJutUBEngKKmk4iH3sD59MBkoxVapS/0wgpCz2u7XsNloxknyvBhzwEs1IbV36D9PwqLPJ2DTu3vMA==} + dependencies: + color-name: 1.1.4 + simple-swizzle: 0.2.2 + dev: false + + /color/3.2.1: + resolution: {integrity: sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==} + dependencies: + color-convert: 1.9.3 + color-string: 1.6.0 + dev: false + + /colors/1.4.0: + resolution: {integrity: sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==} + engines: {node: '>=0.1.90'} + dev: false + + /colorspace/1.1.4: + resolution: {integrity: sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==} + dependencies: + color: 3.2.1 + text-hex: 1.0.0 + dev: false + + /concat-map/0.0.1: + resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=} + dev: true + + /core-util-is/1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + dev: false + + /create-error-class/3.0.2: + resolution: {integrity: sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=} + engines: {node: '>=0.10.0'} + dependencies: + capture-stack-trace: 1.0.1 + dev: false + + /create-require/1.1.1: + resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + dev: true + + /cron/1.8.2: + resolution: {integrity: sha512-Gk2c4y6xKEO8FSAUTklqtfSr7oTq0CiPQeLBG5Fl0qoXpZyMcj1SG59YL+hqq04bu6/IuEA7lMkYDAplQNKkyg==} + dependencies: + moment-timezone: 0.5.33 + dev: false + + /debug/4.3.2: + resolution: {integrity: sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + dev: false + + /diff/4.0.2: + resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} + engines: {node: '>=0.3.1'} + dev: true + + /dotenv/10.0.0: + resolution: {integrity: sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==} + engines: {node: '>=10'} + dev: false + + /duplexer3/0.1.4: + resolution: {integrity: sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=} + dev: false + + /dynamic-dedupe/0.3.0: + resolution: {integrity: sha1-BuRMIj9eTpTXjvnbI6ZRXOL5YqE=} + dependencies: + xtend: 4.0.2 + dev: true + + /enabled/2.0.0: + resolution: {integrity: sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==} + dev: false + + /es-class/2.1.1: + resolution: {integrity: sha1-bsIkO1oeNYHAt+7O4BMMnA1vsrc=} + dev: false + + /fecha/4.2.1: + resolution: {integrity: sha512-MMMQ0ludy/nBs1/o0zVOiKTpG7qMbonKUzjJgQFEuvq6INZ1OraKPRAWkBq5vlKLOUMpmNYG1JoN3oDPUQ9m3Q==} + dev: false + + /fill-range/7.0.1: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + engines: {node: '>=8'} + dependencies: + to-regex-range: 5.0.1 + dev: true + + /fn.name/1.1.0: + resolution: {integrity: sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==} + dev: false + + /follow-redirects/1.14.4: + resolution: {integrity: sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + dev: false + + /fs.realpath/1.0.0: + resolution: {integrity: sha1-FQStJSMVjKpA20onh8sBQRmU6k8=} + dev: true + + /fsevents/2.3.2: + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /function-bind/1.1.1: + resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} + dev: true + + /get-stream/3.0.0: + resolution: {integrity: sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=} + engines: {node: '>=4'} + dev: false + + /glob-parent/5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + dependencies: + is-glob: 4.0.3 + dev: true + + /glob/7.2.0: + resolution: {integrity: sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.0.4 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: true + + /got/6.7.1: + resolution: {integrity: sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=} + engines: {node: '>=4'} + dependencies: + create-error-class: 3.0.2 + duplexer3: 0.1.4 + get-stream: 3.0.0 + is-redirect: 1.0.0 + is-retry-allowed: 1.2.0 + is-stream: 1.1.0 + lowercase-keys: 1.0.1 + safe-buffer: 5.2.1 + timed-out: 4.0.1 + unzip-response: 2.0.1 + url-parse-lax: 1.0.0 + dev: false + + /has/1.0.3: + resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} + engines: {node: '>= 0.4.0'} + dependencies: + function-bind: 1.1.1 + dev: true + + /https-proxy-agent/5.0.0: + resolution: {integrity: sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==} + engines: {node: '>= 6'} + dependencies: + agent-base: 6.0.2 + debug: 4.3.2 + transitivePeerDependencies: + - supports-color + dev: false + + /inflight/1.0.6: + resolution: {integrity: sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=} + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + dev: true + + /inherits/2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + /is-arrayish/0.3.2: + resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} + dev: false + + /is-binary-path/2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + dependencies: + binary-extensions: 2.2.0 + dev: true + + /is-core-module/2.8.0: + resolution: {integrity: sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==} + dependencies: + has: 1.0.3 + dev: true + + /is-extglob/2.1.1: + resolution: {integrity: sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=} + engines: {node: '>=0.10.0'} + dev: true + + /is-glob/4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + dependencies: + is-extglob: 2.1.1 + dev: true + + /is-number/7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + dev: true + + /is-redirect/1.0.0: + resolution: {integrity: sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=} + engines: {node: '>=0.10.0'} + dev: false + + /is-retry-allowed/1.2.0: + resolution: {integrity: sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==} + engines: {node: '>=0.10.0'} + dev: false + + /is-stream/1.1.0: + resolution: {integrity: sha1-EtSj3U5o4Lec6428hBc66A2RykQ=} + engines: {node: '>=0.10.0'} + dev: false + + /is-stream/2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + dev: false + + /isarray/1.0.0: + resolution: {integrity: sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=} + dev: false + + /kuler/2.0.0: + resolution: {integrity: sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==} + dev: false + + /logform/2.3.0: + resolution: {integrity: sha512-graeoWUH2knKbGthMtuG1EfaSPMZFZBIrhuJHhkS5ZseFBrc7DupCzihOQAzsK/qIKPQaPJ/lFQFctILUY5ARQ==} + dependencies: + colors: 1.4.0 + fecha: 4.2.1 + ms: 2.1.2 + safe-stable-stringify: 1.1.1 + triple-beam: 1.3.0 + dev: false + + /lowercase-keys/1.0.1: + resolution: {integrity: sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==} + engines: {node: '>=0.10.0'} + dev: false + + /make-error/1.3.6: + resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + dev: true + + /minimatch/3.0.4: + resolution: {integrity: sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==} + dependencies: + brace-expansion: 1.1.11 + dev: true + + /minimist/1.2.5: + resolution: {integrity: sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==} + dev: true + + /mkdirp/1.0.4: + resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} + engines: {node: '>=10'} + hasBin: true + dev: true + + /moment-timezone/0.5.33: + resolution: {integrity: sha512-PTc2vcT8K9J5/9rDEPe5czSIKgLoGsH8UNpA4qZTVw0Vd/Uz19geE9abbIOQKaAQFcnQ3v5YEXrbSc5BpshH+w==} + dependencies: + moment: 2.29.1 + dev: false + + /moment/2.29.1: + resolution: {integrity: sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==} + + /ms/2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + dev: false + + /normalize-path/3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + dev: true + + /object-assign/4.1.1: + resolution: {integrity: sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=} + engines: {node: '>=0.10.0'} + dev: false + + /once/1.4.0: + resolution: {integrity: sha1-WDsap3WWHUsROsF9nFC6753Xa9E=} + dependencies: + wrappy: 1.0.2 + dev: true + + /one-time/1.0.0: + resolution: {integrity: sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==} + dependencies: + fn.name: 1.1.0 + dev: false + + /path-is-absolute/1.0.1: + resolution: {integrity: sha1-F0uSaHNVNP+8es5r9TpanhtcX18=} + engines: {node: '>=0.10.0'} + dev: true + + /path-parse/1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + dev: true + + /picomatch/2.3.0: + resolution: {integrity: sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==} + engines: {node: '>=8.6'} + dev: true + + /prepend-http/1.0.4: + resolution: {integrity: sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=} + engines: {node: '>=0.10.0'} + dev: false + + /process-nextick-args/2.0.1: + resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + dev: false + + /readable-stream/2.3.7: + resolution: {integrity: sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==} + dependencies: + core-util-is: 1.0.3 + inherits: 2.0.4 + isarray: 1.0.0 + process-nextick-args: 2.0.1 + safe-buffer: 5.1.2 + string_decoder: 1.1.1 + util-deprecate: 1.0.2 + dev: false + + /readable-stream/3.6.0: + resolution: {integrity: sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==} + engines: {node: '>= 6'} + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + dev: false + + /readdirp/3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + dependencies: + picomatch: 2.3.0 + dev: true + + /resolve/1.20.0: + resolution: {integrity: sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==} + dependencies: + is-core-module: 2.8.0 + path-parse: 1.0.7 + dev: true + + /rimraf/2.7.1: + resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==} + hasBin: true + dependencies: + glob: 7.2.0 + dev: true + + /safe-buffer/5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + dev: false + + /safe-buffer/5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + dev: false + + /safe-stable-stringify/1.1.1: + resolution: {integrity: sha512-ERq4hUjKDbJfE4+XtZLFPCDi8Vb1JqaxAPTxWFLBx8XcAlf9Bda/ZJdVezs/NAfsMQScyIlUMx+Yeu7P7rx5jw==} + dev: false + + /should-proxy/1.0.4: + resolution: {integrity: sha1-yAWlAav2lTlgBjSAnmL78ji6NeQ=} + dev: false + + /simple-swizzle/0.2.2: + resolution: {integrity: sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=} + dependencies: + is-arrayish: 0.3.2 + dev: false + + /source-map-support/0.5.20: + resolution: {integrity: sha512-n1lZZ8Ve4ksRqizaBQgxXDgKwttHDhyfQjA6YZZn8+AroHbsIz+JjwxQDxbp+7y5OYCI8t1Yk7etjD9CRd2hIw==} + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + dev: true + + /source-map/0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + dev: true + + /stack-trace/0.0.10: + resolution: {integrity: sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=} + dev: false + + /string_decoder/1.1.1: + resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + dependencies: + safe-buffer: 5.1.2 + dev: false + + /string_decoder/1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + dependencies: + safe-buffer: 5.2.1 + dev: false + + /strip-bom/3.0.0: + resolution: {integrity: sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=} + engines: {node: '>=4'} + dev: true + + /strip-json-comments/2.0.1: + resolution: {integrity: sha1-PFMZQukIwml8DsNEhYwobHygpgo=} + engines: {node: '>=0.10.0'} + dev: true + + /text-hex/1.0.0: + resolution: {integrity: sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==} + dev: false + + /timed-out/4.0.1: + resolution: {integrity: sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=} + engines: {node: '>=0.10.0'} + dev: false + + /to-regex-range/5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + dependencies: + is-number: 7.0.0 + dev: true + + /tree-kill/1.2.2: + resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} + hasBin: true + dev: true + + /triple-beam/1.3.0: + resolution: {integrity: sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==} + dev: false + + /ts-node-dev/1.1.8_typescript@4.4.4: + resolution: {integrity: sha512-Q/m3vEwzYwLZKmV6/0VlFxcZzVV/xcgOt+Tx/VjaaRHyiBcFlV0541yrT09QjzzCxlDZ34OzKjrFAynlmtflEg==} + engines: {node: '>=0.8.0'} + hasBin: true + peerDependencies: + node-notifier: '*' + typescript: '*' + peerDependenciesMeta: + node-notifier: + optional: true + dependencies: + chokidar: 3.5.2 + dynamic-dedupe: 0.3.0 + minimist: 1.2.5 + mkdirp: 1.0.4 + resolve: 1.20.0 + rimraf: 2.7.1 + source-map-support: 0.5.20 + tree-kill: 1.2.2 + ts-node: 9.1.1_typescript@4.4.4 + tsconfig: 7.0.0 + typescript: 4.4.4 + dev: true + + /ts-node/9.1.1_typescript@4.4.4: + resolution: {integrity: sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==} + engines: {node: '>=10.0.0'} + hasBin: true + peerDependencies: + typescript: '>=2.7' + dependencies: + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + source-map-support: 0.5.20 + typescript: 4.4.4 + yn: 3.1.1 + dev: true + + /tsconfig/7.0.0: + resolution: {integrity: sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw==} + dependencies: + '@types/strip-bom': 3.0.0 + '@types/strip-json-comments': 0.0.30 + strip-bom: 3.0.0 + strip-json-comments: 2.0.1 + dev: true + + /typescript/4.4.4: + resolution: {integrity: sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA==} + engines: {node: '>=4.2.0'} + hasBin: true + dev: true + + /unzip-response/2.0.1: + resolution: {integrity: sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=} + engines: {node: '>=4'} + dev: false + + /url-parse-lax/1.0.0: + resolution: {integrity: sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=} + engines: {node: '>=0.10.0'} + dependencies: + prepend-http: 1.0.4 + dev: false + + /url-pattern/1.0.3: + resolution: {integrity: sha1-BAkpJHGyTyPFDWWkeTF5PStaz8E=} + engines: {node: '>=0.12.0'} + dev: false + + /util-deprecate/1.0.2: + resolution: {integrity: sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=} + dev: false + + /winston-transport/4.4.0: + resolution: {integrity: sha512-Lc7/p3GtqtqPBYYtS6KCN3c77/2QCev51DvcJKbkFPQNoj1sinkGwLGFDxkXY9J6p9+EPnYs+D90uwbnaiURTw==} + engines: {node: '>= 6.4.0'} + dependencies: + readable-stream: 2.3.7 + triple-beam: 1.3.0 + dev: false + + /winston/3.3.3: + resolution: {integrity: sha512-oEXTISQnC8VlSAKf1KYSSd7J6IWuRPQqDdo8eoRNaYKLvwSb5+79Z3Yi1lrl6KDpU6/VWaxpakDAtb1oQ4n9aw==} + engines: {node: '>= 6.4.0'} + dependencies: + '@dabh/diagnostics': 2.0.2 + async: 3.2.1 + is-stream: 2.0.1 + logform: 2.3.0 + one-time: 1.0.0 + readable-stream: 3.6.0 + stack-trace: 0.0.10 + triple-beam: 1.3.0 + winston-transport: 4.4.0 + dev: false + + /wrappy/1.0.2: + resolution: {integrity: sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=} + dev: true + + /xtend/4.0.2: + resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} + engines: {node: '>=0.4'} + dev: true + + /yn/3.1.1: + resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} + engines: {node: '>=6'} + dev: true diff --git a/script.js b/script.js deleted file mode 100644 index 40cc840..0000000 --- a/script.js +++ /dev/null @@ -1,69 +0,0 @@ -const { readFileSync, writeFileSync, existsSync } = require('fs') -const Cloudflare = require('cloudflare') -const Axios = require('axios') -const { CronJob } = require('cron') - -require('dotenv').config() - -const { EMAIL, KEY, ZONE, DNS_RECORD, CRON, RESOLVER } = process.env - -const cf = Cloudflare({ - email: EMAIL, - key: KEY, -}) - -function log(message) { - const timestamp = new Date().toISOString().replace(/T/, ' ').replace(/\..+/, '') - console.log(timestamp + '\t' + message) -} - -async function getCurrentIp() { - const { data } = await Axios({ - url: RESOLVER || 'https://api.ipify.org/', - method: 'GET', - }) - return data -} - -async function checkIfUpdateIsRequired() { - const LOG = './ip.log' - const current = await getCurrentIp() - const saved = existsSync(LOG) ? readFileSync(LOG, 'utf-8') : null - - if (current === saved) return false - else { - writeFileSync(LOG, current, { encoding: 'utf-8' }) - return current - } -} - -async function update(newIP) { - const { result: zones } = await cf.zones.browse({ name: ZONE }) - if (!zones.length) throw new Error(`No ZONE "${ZONE}" found`) - - const zoneId = zones[0].id - const { result: records } = await cf.dnsRecords.browse(zoneId, { name: DNS_RECORD, type: 'A' }) - - const recordAlreadyExists = records.length - if (recordAlreadyExists) { - const { id: recordId, ...rest } = records[0] - await cf.dnsRecords.edit(zoneId, recordId, { ...rest, content: newIP }) - log(`Updated:\t${DNS_RECORD} → ${newIP} `) - } else { - await cf.dnsRecords.add(zoneId, { - name: DNS_RECORD, - type: 'A', - content: newIP, - }) - log(`Created:\t${DNS_RECORD} → ${newIP} `) - } -} - -async function main() { - const changed = await checkIfUpdateIsRequired() - log(`Running. Update required: ${!!changed}`) - if (changed) await update(changed).catch((e) => console.error(e.message)) -} - -new CronJob(CRON || '*/5 * * * *', main, null, true, null, null, true) -log('Started service.') diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..6b6ae4a --- /dev/null +++ b/src/index.ts @@ -0,0 +1,114 @@ +import Cloudflare from 'cloudflare' +import Axios from 'axios' +import { CronJob } from 'cron' +import { config } from 'dotenv' +import winston from 'winston' + +const logger = winston.createLogger({ + level: 'info', + transports: [ + new winston.transports.Console({ + format: winston.format.combine(winston.format.timestamp(), winston.format.colorize(), winston.format.simple()), + }), + ], +}) + +const Cache = new Map() + +async function getCurrentIp(resolver?: string): Promise { + const { data } = await Axios({ + url: resolver || 'https://api.ipify.org/', + method: 'GET', + }) + return data as string +} + +function checkIfUpdateIsRequired(newIP: string): boolean { + // Check if IP has changed. + const current = Cache.get('ip') + if (newIP !== current) { + Cache.set('ip', newIP) + return true + } + return false +} + +type DNSRecord = { + zone: string + record: string + ip: string +} +async function update(cf: Cloudflare, options: DNSRecord) { + // Find zone + if (!Cache.has('zone')) { + logger.debug('Fetching zone') + const zones: { result: { id: string; name: string }[] } = (await cf.zones.browse()) as any + const zone = zones.result.find((z) => z.name === options.zone) + if (!zone) { + logger.error(`Zone "${options.zone}"" not found`) + process.exit(1) + } + Cache.set('zone', zone.id) + } + + const zoneId = Cache.get('zone')! + logger.debug(`Zone ID: ${zoneId}`) + + // Set record + const records: { result: { id: string; type: string; name: string; ttl: number }[] } = (await cf.dnsRecords.browse( + zoneId + )) as any + const relevant = records.result.filter((r) => r.name === options.record && r.type === 'A') + if (relevant.length === 0) { + // Create DNS Record + logger.debug('Creating DNS record') + await cf.dnsRecords.add(zoneId, { + type: 'A', + name: options.record, + content: options.ip, + ttl: 1, + }) + } else { + if (relevant.length > 1) { + // Delete other records as they cannot all point to the same IP + logger.debug('Deleting other DNS records') + for (const record of relevant.slice(1)) { + await cf.dnsRecords.del(zoneId, record.id) + } + } + // Update DNS Record + logger.debug('Updating DNS record') + const record = relevant[0]! + await cf.dnsRecords.edit(zoneId, record.id, { + type: 'A', + name: options.record, + content: options.ip, + ttl: record.ttl, + }) + logger.info(`Updated DNS record ${record.name}`) + } +} + +async function main() { + config() + const { EMAIL, KEY, TOKEN, ZONE, DNS_RECORD, CRON, RESOLVER } = process.env + if (!ZONE || !DNS_RECORD) { + logger.error('Missing environment variables') + process.exit(1) + } + + // Initialize Cloudflare + const cf = new Cloudflare(TOKEN ? { token: TOKEN } : { email: EMAIL, key: KEY }) + + async function fn() { + const ip = await getCurrentIp(RESOLVER) + const changed = checkIfUpdateIsRequired(ip) + logger.info(`Running. Update required: ${!!changed}`) + if (changed) await update(cf, { ip, record: DNS_RECORD!, zone: ZONE! }).catch((e) => logger.error(e.message)) + } + + new CronJob(CRON || '*/5 * * * *', fn, null, true, undefined, null, true) + logger.info('Started service.') +} + +main() diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..e36e77a --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,100 @@ +{ + "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. */ + + /* Language and Environment */ + "target": "es2020" /* 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": "./src" /* 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 ``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`. */ + + /* 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. */ + + /* 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. */, + + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + } +} diff --git a/yarn.lock b/yarn.lock deleted file mode 100644 index 154470f..0000000 --- a/yarn.lock +++ /dev/null @@ -1,202 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -agent-base@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee" - integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg== - dependencies: - es6-promisify "^5.0.0" - -autocreate@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/autocreate/-/autocreate-1.2.0.tgz#522167992c4172c15479e5f88f3486a452a40cba" - integrity sha1-UiFnmSxBcsFUeeX4jzSGpFKkDLo= - -axios@^0.21.1: - version "0.21.1" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.1.tgz#22563481962f4d6bde9a76d516ef0e5d3c09b2b8" - integrity sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA== - dependencies: - follow-redirects "^1.10.0" - -capture-stack-trace@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz#a6c0bbe1f38f3aa0b92238ecb6ff42c344d4135d" - integrity sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw== - -cloudflare@^2.7.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/cloudflare/-/cloudflare-2.7.0.tgz#ff9249a63ff9b662bd863da21e965c8f82f76012" - integrity sha512-yhroBpn2VBczFwiRLpyUc431XiWE+xNs8YvtjAsj1vEA1pVwhpje6BzgLW5iZbulmCuPX48lvX8HizeMWk713g== - dependencies: - autocreate "^1.1.0" - es-class "^2.1.1" - got "^6.3.0" - https-proxy-agent "^2.1.1" - object-assign "^4.1.0" - should-proxy "^1.0.4" - url-pattern "^1.0.3" - -create-error-class@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/create-error-class/-/create-error-class-3.0.2.tgz#06be7abef947a3f14a30fd610671d401bca8b7b6" - integrity sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y= - dependencies: - capture-stack-trace "^1.0.0" - -cron@^1.8.2: - version "1.8.2" - resolved "https://registry.yarnpkg.com/cron/-/cron-1.8.2.tgz#4ac5e3c55ba8c163d84f3407bde94632da8370ce" - integrity sha512-Gk2c4y6xKEO8FSAUTklqtfSr7oTq0CiPQeLBG5Fl0qoXpZyMcj1SG59YL+hqq04bu6/IuEA7lMkYDAplQNKkyg== - dependencies: - moment-timezone "^0.5.x" - -debug@^3.1.0: - version "3.2.7" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" - integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== - dependencies: - ms "^2.1.1" - -dotenv@^8.2.0: - version "8.5.1" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.5.1.tgz#e3a4c7862daba51b92bce0da5c349f11faa28663" - integrity sha512-qC1FbhCH7UH7B+BcRNUDhAk04d/n+tnGGB1ctwndZkVFeehYJOn39pRWWzmdzpFqImyX1KB8tO0DCHLf8yRaYQ== - -duplexer3@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" - integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= - -es-class@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/es-class/-/es-class-2.1.1.tgz#6ec2243b5a1e3581c0b7eecee0130c9c0d6fb2b7" - integrity sha1-bsIkO1oeNYHAt+7O4BMMnA1vsrc= - -es6-promise@^4.0.3: - version "4.2.8" - resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" - integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== - -es6-promisify@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" - integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM= - dependencies: - es6-promise "^4.0.3" - -follow-redirects@^1.10.0: - version "1.14.0" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.0.tgz#f5d260f95c5f8c105894491feee5dc8993b402fe" - integrity sha512-0vRwd7RKQBTt+mgu87mtYeofLFZpTas2S9zY+jIeuLJMNvudIgF52nr19q40HOwH5RrhWIPuj9puybzSJiRrVg== - -get-stream@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" - integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= - -got@^6.3.0: - version "6.7.1" - resolved "https://registry.yarnpkg.com/got/-/got-6.7.1.tgz#240cd05785a9a18e561dc1b44b41c763ef1e8db0" - integrity sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA= - dependencies: - create-error-class "^3.0.0" - duplexer3 "^0.1.4" - get-stream "^3.0.0" - is-redirect "^1.0.0" - is-retry-allowed "^1.0.0" - is-stream "^1.0.0" - lowercase-keys "^1.0.0" - safe-buffer "^5.0.1" - timed-out "^4.0.0" - unzip-response "^2.0.1" - url-parse-lax "^1.0.0" - -https-proxy-agent@^2.1.1: - version "2.2.4" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b" - integrity sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg== - dependencies: - agent-base "^4.3.0" - debug "^3.1.0" - -is-redirect@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24" - integrity sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ= - -is-retry-allowed@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz#d778488bd0a4666a3be8a1482b9f2baafedea8b4" - integrity sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg== - -is-stream@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" - integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= - -lowercase-keys@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" - integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== - -moment-timezone@^0.5.x: - version "0.5.33" - resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.33.tgz#b252fd6bb57f341c9b59a5ab61a8e51a73bbd22c" - integrity sha512-PTc2vcT8K9J5/9rDEPe5czSIKgLoGsH8UNpA4qZTVw0Vd/Uz19geE9abbIOQKaAQFcnQ3v5YEXrbSc5BpshH+w== - dependencies: - moment ">= 2.9.0" - -"moment@>= 2.9.0": - version "2.29.1" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3" - integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ== - -ms@^2.1.1: - version "2.1.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== - -object-assign@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= - -prepend-http@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" - integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= - -safe-buffer@^5.0.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -should-proxy@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/should-proxy/-/should-proxy-1.0.4.tgz#c805a501abf69539600634809e62fbf238ba35e4" - integrity sha1-yAWlAav2lTlgBjSAnmL78ji6NeQ= - -timed-out@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" - integrity sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8= - -unzip-response@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97" - integrity sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c= - -url-parse-lax@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73" - integrity sha1-evjzA2Rem9eaJy56FKxovAYJ2nM= - dependencies: - prepend-http "^1.0.1" - -url-pattern@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/url-pattern/-/url-pattern-1.0.3.tgz#0409292471b24f23c50d65a47931793d2b5acfc1" - integrity sha1-BAkpJHGyTyPFDWWkeTF5PStaz8E=