From 3ca15c532f68b3c434df9f6ee9a242c290db5d4b Mon Sep 17 00:00:00 2001 From: Niccolo Borgioli Date: Tue, 27 Feb 2024 17:59:00 +0100 Subject: [PATCH] use bun and remove some deps --- .dockerignore | 3 +- .gitignore | 1 - CHANGELOG.md | 7 ++ Dockerfile | 25 +--- README.md | 2 +- bun.lockb | Bin 0 -> 17556 bytes package.json | 19 ++- pnpm-lock.yaml | 310 ---------------------------------------------- src/cloudflare.ts | 14 ++- src/config.ts | 17 ++- src/index.ts | 16 ++- src/runner.ts | 10 +- tsconfig.json | 4 +- 13 files changed, 61 insertions(+), 367 deletions(-) create mode 100755 bun.lockb delete mode 100644 pnpm-lock.yaml diff --git a/.dockerignore b/.dockerignore index 9575226..c12bc57 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,5 +1,4 @@ * !src -!tsconfig.json !package.json -!pnpm-lock.yaml +!bun.lockb diff --git a/.gitignore b/.gitignore index 828f5a3..da9168b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ .env ip.log -dist node_modules .vscode diff --git a/CHANGELOG.md b/CHANGELOG.md index d704978..90aa46f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.4.0] - 2024-02-27 + +### Changed + +- Moved to bun. +- Removed some dependencies. + ## [1.3.4] - 2024-02-27 ### Security diff --git a/Dockerfile b/Dockerfile index 11f31f6..2f26938 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,23 +1,10 @@ -FROM node:20-alpine as base -# PNPM -ENV PNPM_HOME="/pnpm" -ENV PATH="$PNPM_HOME:$PATH" -RUN corepack enable -# Setup -ENV CI=true +FROM oven/bun:1 as base + WORKDIR /app -ADD ./package.json ./pnpm-lock.yaml ./ +COPY package.json bun.lockb /app/ +RUN bun install --production --frozen-lockfile - -FROM base as builder -RUN pnpm install -ADD . . -RUN pnpm run build - -FROM base -RUN pnpm install --prod -COPY --from=builder /app/dist/ /app/dist/ +COPY . . STOPSIGNAL SIGTERM - -CMD ["pnpm", "start"] +CMD ["bun", "."] diff --git a/README.md b/README.md index 77f1d65..cd6fd5b 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ docker-compose up -d | `ZONE` | | Cloudflare zone where your domain is. | | `DNS_RECORD` | | The actual DNS record that should be updated. | | `PROXIED` | `true` | Whether the record is proxied by CloudFlare or not. | -| `CRON` | `*/5 * * * *` | Frequency of updates. | +| `CRON` | `*/5 * * * *` | Frequency of updates. The [following syntax](https://croner.56k.guru/usage/pattern/) is supported | | `RESOLVER` | `https://api.ipify.org/` | The endpoint used to determine your public ip. | | `LOG_LEVEL` | `info` | Log level to run at. See [winston](https://github.com/winstonjs/winston#logging-levels) for possible values | diff --git a/bun.lockb b/bun.lockb new file mode 100755 index 0000000000000000000000000000000000000000..0dd66186ea225d7a028d605cee3a0b5f0f48cf71 GIT binary patch literal 17556 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 literal 0 HcmV?d00001 diff --git a/package.json b/package.json index 302759a..5c0a275 100644 --- a/package.json +++ b/package.json @@ -1,23 +1,20 @@ { - "version": "1.3.4", + "version": "1.4.0", "license": "MIT", "type": "module", - "main": "dist", + "main": "./src/index.ts", "scripts": { - "build": "tsc", - "dev": "tsc -w", - "start": "node ." + "check": "tsc --noEmit", + "dev": "bun --watch ./src/index.ts", + "start": "bun ./src/index.ts" }, "dependencies": { "axios": "^1.6.7", - "dotenv": "^16.4.5", - "node-cron": "^3.0.3", + "croner": "^8.0.1", "winston": "^3.11.0" }, "devDependencies": { - "@types/node": "^20.11.20", - "@types/node-cron": "^3.0.11", + "@types/bun": "^1.0.7", "typescript": "^5.3.3" - }, - "packageManager": "pnpm@8.15.4" + } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml deleted file mode 100644 index 09d1f90..0000000 --- a/pnpm-lock.yaml +++ /dev/null @@ -1,310 +0,0 @@ -lockfileVersion: '6.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -dependencies: - axios: - specifier: ^1.6.7 - version: 1.6.7 - dotenv: - specifier: ^16.4.5 - version: 16.4.5 - node-cron: - specifier: ^3.0.3 - version: 3.0.3 - winston: - specifier: ^3.11.0 - version: 3.11.0 - -devDependencies: - '@types/node': - specifier: ^20.11.20 - version: 20.11.20 - '@types/node-cron': - specifier: ^3.0.11 - version: 3.0.11 - typescript: - specifier: ^5.3.3 - version: 5.3.3 - -packages: - - /@colors/colors@1.6.0: - resolution: {integrity: sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==} - engines: {node: '>=0.1.90'} - dev: false - - /@dabh/diagnostics@2.0.3: - resolution: {integrity: sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==} - dependencies: - colorspace: 1.1.4 - enabled: 2.0.0 - kuler: 2.0.0 - dev: false - - /@types/node-cron@3.0.11: - resolution: {integrity: sha512-0ikrnug3/IyneSHqCBeslAhlK2aBfYek1fGo4bP4QnZPmiqSGRK+Oy7ZMisLWkesffJvQ1cqAcBnJC+8+nxIAg==} - dev: true - - /@types/node@20.11.20: - resolution: {integrity: sha512-7/rR21OS+fq8IyHTgtLkDK949uzsa6n8BkziAKtPVpugIkO6D+/ooXMvzXxDnZrmtXVfjb1bKQafYpb8s89LOg==} - dependencies: - undici-types: 5.26.5 - dev: true - - /@types/triple-beam@1.3.5: - resolution: {integrity: sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==} - dev: false - - /async@3.2.5: - resolution: {integrity: sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==} - dev: false - - /asynckit@0.4.0: - resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} - dev: false - - /axios@1.6.7: - resolution: {integrity: sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==} - dependencies: - follow-redirects: 1.15.5 - form-data: 4.0.0 - proxy-from-env: 1.1.0 - transitivePeerDependencies: - - debug - 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: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} - dev: false - - /color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - dev: false - - /color-string@1.9.1: - resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} - 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.9.1 - 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 - - /combined-stream@1.0.8: - resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} - engines: {node: '>= 0.8'} - dependencies: - delayed-stream: 1.0.0 - dev: false - - /delayed-stream@1.0.0: - resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} - engines: {node: '>=0.4.0'} - dev: false - - /dotenv@16.4.5: - resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==} - engines: {node: '>=12'} - dev: false - - /enabled@2.0.0: - resolution: {integrity: sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==} - dev: false - - /fecha@4.2.3: - resolution: {integrity: sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==} - dev: false - - /fn.name@1.1.0: - resolution: {integrity: sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==} - dev: false - - /follow-redirects@1.15.5: - resolution: {integrity: sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==} - engines: {node: '>=4.0'} - peerDependencies: - debug: '*' - peerDependenciesMeta: - debug: - optional: true - dev: false - - /form-data@4.0.0: - resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} - engines: {node: '>= 6'} - dependencies: - asynckit: 0.4.0 - combined-stream: 1.0.8 - mime-types: 2.1.35 - dev: false - - /inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - dev: false - - /is-arrayish@0.3.2: - resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} - dev: false - - /is-stream@2.0.1: - resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} - engines: {node: '>=8'} - dev: false - - /kuler@2.0.0: - resolution: {integrity: sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==} - dev: false - - /logform@2.6.0: - resolution: {integrity: sha512-1ulHeNPp6k/LD8H91o7VYFBng5i1BDE7HoKxVbZiGFidS1Rj65qcywLxX+pVfAPoQJEjRdvKcusKwOupHCVOVQ==} - engines: {node: '>= 12.0.0'} - dependencies: - '@colors/colors': 1.6.0 - '@types/triple-beam': 1.3.5 - fecha: 4.2.3 - ms: 2.1.3 - safe-stable-stringify: 2.4.3 - triple-beam: 1.4.1 - dev: false - - /mime-db@1.52.0: - resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} - engines: {node: '>= 0.6'} - dev: false - - /mime-types@2.1.35: - resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} - engines: {node: '>= 0.6'} - dependencies: - mime-db: 1.52.0 - dev: false - - /ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - dev: false - - /node-cron@3.0.3: - resolution: {integrity: sha512-dOal67//nohNgYWb+nWmg5dkFdIwDm8EpeGYMekPMrngV3637lqnX0lbUcCtgibHTz6SEz7DAIjKvKDFYCnO1A==} - engines: {node: '>=6.0.0'} - dependencies: - uuid: 8.3.2 - dev: false - - /one-time@1.0.0: - resolution: {integrity: sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==} - dependencies: - fn.name: 1.1.0 - dev: false - - /proxy-from-env@1.1.0: - resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} - dev: false - - /readable-stream@3.6.2: - resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} - engines: {node: '>= 6'} - dependencies: - inherits: 2.0.4 - string_decoder: 1.3.0 - util-deprecate: 1.0.2 - dev: false - - /safe-buffer@5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - dev: false - - /safe-stable-stringify@2.4.3: - resolution: {integrity: sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==} - engines: {node: '>=10'} - dev: false - - /simple-swizzle@0.2.2: - resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} - dependencies: - is-arrayish: 0.3.2 - dev: false - - /stack-trace@0.0.10: - resolution: {integrity: sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==} - dev: false - - /string_decoder@1.3.0: - resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} - dependencies: - safe-buffer: 5.2.1 - dev: false - - /text-hex@1.0.0: - resolution: {integrity: sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==} - dev: false - - /triple-beam@1.4.1: - resolution: {integrity: sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==} - engines: {node: '>= 14.0.0'} - dev: false - - /typescript@5.3.3: - resolution: {integrity: sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==} - engines: {node: '>=14.17'} - hasBin: true - dev: true - - /undici-types@5.26.5: - resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} - dev: true - - /util-deprecate@1.0.2: - resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - dev: false - - /uuid@8.3.2: - resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} - hasBin: true - dev: false - - /winston-transport@4.7.0: - resolution: {integrity: sha512-ajBj65K5I7denzer2IYW6+2bNIVqLGDHqDw3Ow8Ohh+vdW+rv4MZ6eiDvHoKhfJFZ2auyN8byXieDDJ96ViONg==} - engines: {node: '>= 12.0.0'} - dependencies: - logform: 2.6.0 - readable-stream: 3.6.2 - triple-beam: 1.4.1 - dev: false - - /winston@3.11.0: - resolution: {integrity: sha512-L3yR6/MzZAOl0DsysUXHVjOwv8mKZ71TrA/41EIduGpOOV5LQVodqN+QdQ6BS6PJ/RdIshZhq84P/fStEZkk7g==} - engines: {node: '>= 12.0.0'} - dependencies: - '@colors/colors': 1.6.0 - '@dabh/diagnostics': 2.0.3 - async: 3.2.5 - is-stream: 2.0.1 - logform: 2.6.0 - one-time: 1.0.0 - readable-stream: 3.6.2 - safe-stable-stringify: 2.4.3 - stack-trace: 0.0.10 - triple-beam: 1.4.1 - winston-transport: 4.7.0 - dev: false diff --git a/src/cloudflare.ts b/src/cloudflare.ts index 24463d4..0221794 100644 --- a/src/cloudflare.ts +++ b/src/cloudflare.ts @@ -20,6 +20,8 @@ type DNSRecord = { type DNSRecordCreate = Pick type DNSRecordPatch = Partial +const l = logger.child({ context: 'cloudflare' }) + const Base = axios.create({ baseURL: 'https://api.cloudflare.com/client/v4', headers: { @@ -80,27 +82,27 @@ export const API = { export async function update(ip: string) { // Find zone if (!Cache.has('zone')) { - logger.debug('Fetching zone') + l.debug('Fetching zone') const zone = await API.zones.findByName(Config.dns.zone) if (!zone) { - logger.error(`Zone "${Config.dns.zone}"" not found`) + l.error(`Zone "${Config.dns.zone}" not found`) process.exit(1) } Cache.set('zone', zone) } const zoneId = Cache.get('zone')! - logger.debug(`Zone ID: ${zoneId}`) + l.debug(`Zone ID: ${zoneId}`) // Set record const records = await API.records.find(zoneId) - logger.debug('Updating record', ip) + l.debug('Updating record', ip) switch (records.length) { case 0: // Create DNS Record - logger.debug('Creating DNS record') + l.debug('Creating DNS record') await API.records.create(zoneId, { content: ip, name: Config.dns.record, @@ -114,7 +116,7 @@ export async function update(ip: string) { break default: // More than one record, delete all but the first - logger.debug('Deleting other DNS records') + l.debug('Deleting other DNS records') for (const record of records.slice(1)) { await API.records.remove(zoneId, record.id) } diff --git a/src/config.ts b/src/config.ts index 35bcd5b..3cc2dc7 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,7 +1,5 @@ -import { config } from 'dotenv' -import { validate } from 'node-cron' - -config() +import { Cron } from 'croner' +import pkg from '../package.json' function getEnv(key: string, fallback: string, parse?: undefined, validator?: (s: string) => boolean): string function getEnv(key: string, fallback: T, parse: (value: string) => T, validator?: (T: string) => boolean): T @@ -31,7 +29,7 @@ function isPresent(s: string): boolean { } export const Config = { - version: getEnv('npm_package_version', 'unknown'), + version: pkg.version, logging: { level: getEnv('LOG_LEVEL', 'info'), }, @@ -44,7 +42,14 @@ export const Config = { proxied: getEnv('PROXIED', false, parseBoolean), }, runner: { - cron: getEnv('CRON', '*/5 * * * *', undefined, (s) => validate(s)), + cron: getEnv('CRON', '*/5 * * * *', undefined, (s) => { + try { + new Cron(s) + return true + } catch { + return false + } + }), resolver: getEnv('RESOLVER', 'https://api.ipify.org'), }, } diff --git a/src/index.ts b/src/index.ts index 6b6b950..b9f0a6f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,14 +1,20 @@ -import { schedule } from 'node-cron' -import process from 'process' +import { Cron } from 'croner' +import process from 'node:process' import { Config } from './config.js' import { logger } from './logger.js' import { loop } from './runner.js' async function main() { - const cron = schedule(Config.runner.cron, loop) - logger.info('Started service.', { version: Config.version }) - logger.debug('Config', Config) + const cron = new Cron(Config.runner.cron, { protect: true }, loop) + logger.info('started service', { version: Config.version }) + logger.debug('config', Config) + + const nextRun = cron.nextRun() + if (nextRun) { + const pretty = new Intl.DateTimeFormat(undefined, { dateStyle: 'long', timeStyle: 'long' }).format(nextRun) + logger.info(`next run scheduled for ${pretty}`, { nextRunAt: nextRun }) + } function terminate() { logger.info('Stopping service.') diff --git a/src/runner.ts b/src/runner.ts index 26cf358..2813472 100644 --- a/src/runner.ts +++ b/src/runner.ts @@ -2,17 +2,19 @@ import { update } from './cloudflare.js' import { checkIfUpdateIsRequired, getCurrentIp } from './ip.js' import { logger } from './logger.js' +const l = logger.child({ context: 'runner' }) + export async function loop() { const ip = await getCurrentIp() const changed = checkIfUpdateIsRequired(ip) - logger.info(`Running. Update required: ${!!changed}`) + l.info(`Running. Update required: ${!!changed}`) if (changed) { try { await update(ip) - logger.info('Successfully updated DNS record') + l.info('Successfully updated DNS record') } catch (e) { - logger.error(e) - logger.error('Failed to update DNS record') + l.error(e) + l.error('Failed to update DNS record') } } } diff --git a/tsconfig.json b/tsconfig.json index e075d06..52f0ae6 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,8 +3,8 @@ "target": "ES2022", "module": "ES2022", "rootDir": "./src", - "moduleResolution": "node", - "outDir": "./dist", + "moduleResolution": "Bundler", + "noEmit": true, "esModuleInterop": true, "strict": true, "skipLibCheck": true