diff --git a/package.json b/package.json index c687e5f712a..4dad71cb813 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "dev:cron:first-data-broker-removal-fixed": "tsx --tsconfig tsconfig.cronjobs.json src/scripts/cronjobs/firstDataBrokerRemovalFixed.tsx", "dev:cron:monthly-activity": "tsx --tsconfig tsconfig.cronjobs.json src/scripts/cronjobs/monthlyActivity.tsx", "dev:cron:db-delete-unverified-subscribers": "tsx --tsconfig tsconfig.cronjobs.json src/scripts/cronjobs/deleteUnverifiedSubscribers.ts", + "dev:cron:onerep-limits-alert": "tsx --tsconfig tsconfig.cronjobs.json src/scripts/cronjobs/onerepStatsAlert.ts", "dev:nimbus": "node --watch-path config/nimbus.yaml src/scripts/build/nimbusTypes.js", "build": "npm run get-location-data && npm run build-glean && npm run build-nimbus && next build && npm run build-cronjobs", "cloudrun": "npm run db:migrate && npm start", @@ -28,7 +29,7 @@ "cron:db-delete-unverified-subscribers": "node dist/scripts/cronjobs/deleteUnverifiedSubscribers.js", "cron:db-pull-breaches": "node src/scripts/syncBreaches.js", "cron:remote-settings-pull-breaches": "node scripts/updatebreaches.js", - "cron:onerep-limits-alert": "node src/scripts/onerepStatsAlert.js", + "cron:onerep-limits-alert": "node dist/scripts/cronjobs/onerepStatsAlert.js", "db:migrate": "node -r dotenv-flow/config node_modules/knex/bin/cli.js migrate:latest --knexfile src/db/knexfile.js", "db:rollback": "node -r dotenv-flow/config node_modules/knex/bin/cli.js migrate:rollback --knexfile src/db/knexfile.js", "prepare": "husky", diff --git a/src/db/tables/stats.js b/src/db/tables/stats.js index 5f537735a03..79eccf3944c 100644 --- a/src/db/tables/stats.js +++ b/src/db/tables/stats.js @@ -14,7 +14,7 @@ * @param {string} name * @param {string} current * @param {string} max - * @returns {Promise} updated subscriber + * @returns {Promise} inserted stats */ export async function addOnerepStats (name, current, max) { const res = await knex("stats").insert({ name, current, max, type: "onerep"}).returning("*"); @@ -22,7 +22,7 @@ export async function addOnerepStats (name, current, max) { } /** - * @returns {object} + * @returns {Promise | undefined>} stats */ export async function getOnerepStats () { const res = await knex("stats").select("name", "current", "max").where("type", "onerep"); diff --git a/src/knex-tables.d.ts b/src/knex-tables.d.ts index 0ebdf1d5141..b5d58d3197c 100644 --- a/src/knex-tables.d.ts +++ b/src/knex-tables.d.ts @@ -312,6 +312,20 @@ declare module "knex/types/tables" { "id" | "created_at" | "updated_at" >; + interface StatsRow { + id: number; + name: string; + current: string; + max: string; + type: string; + created_at: Date; + modified_at: Date; + } + type StatsAutoInsertedColumns = Extract< + keyof StatsRow, + "id" | "created_at" | "modified_at" + >; + interface Tables { attributions: Knex.CompositeTableType< AttributionRow, @@ -430,11 +444,14 @@ declare module "knex/types/tables" { Partial> & Pick >; - } - interface StatsRow { - name: string; - current: string; - max: string; - type: string; + + stats: Knex.CompositeTableType< + StatsRow, + // On updates, auto-generated columns cannot be set: + Omit & Partial, + // On updates, don't allow updating the ID and created date; all other fields are optional, except modified_at: + Partial> & + Pick + >; } } diff --git a/src/scripts/onerepStatsAlert.js b/src/scripts/cronjobs/onerepStatsAlert.ts similarity index 80% rename from src/scripts/onerepStatsAlert.js rename to src/scripts/cronjobs/onerepStatsAlert.ts index 596dcf81df5..9af4f5a28c1 100644 --- a/src/scripts/onerepStatsAlert.js +++ b/src/scripts/cronjobs/onerepStatsAlert.ts @@ -2,16 +2,19 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +import "dotenv-flow/config"; import Sentry from "@sentry/nextjs"; -import { addOnerepStats, knexStats } from "../db/tables/stats.js"; +import { addOnerepStats, knexStats } from "../../db/tables/stats.js"; const SENTRY_SLUG = "cron-onerep-stats-alerts"; -const MAX_MANUAL_SCANS = parseInt(process.env.MAX_MANUAL_SCANS) || 0; -const MAX_INITIAL_SCANS = parseInt(process.env.MAX_INITIAL_SCANS) || 0; -const MAX_PROFILES_ACTIVATED = - parseInt(process.env.MAX_PROFILES_ACTIVATED) || 0; -const MAX_PROFILES_CREATED = parseInt(process.env.MAX_PROFILES_CREATED) || 0; +const parseEnvVarNr = (value: string | undefined) => parseInt(value ?? "0", 10); +const MAX_MANUAL_SCANS = parseEnvVarNr(process.env.MAX_MANUAL_SCANS); +const MAX_INITIAL_SCANS = parseEnvVarNr(process.env.MAX_INITIAL_SCANS); +const MAX_PROFILES_ACTIVATED = parseEnvVarNr( + process.env.MAX_PROFILES_ACTIVATED, +); +const MAX_PROFILES_CREATED = parseEnvVarNr(process.env.MAX_PROFILES_CREATED); Sentry.init({ environment: process.env.APP_ENV, @@ -52,7 +55,7 @@ export async function checkStats() { } // TODO use the shared version when this is converted to Typescript. -async function onerepFetch(path, options = {}) { +async function onerepFetch(path: string, options: RequestInit = {}) { const onerepApiBase = process.env.ONEREP_API_BASE; if (!onerepApiBase) { throw new Error("ONEREP_API_BASE env var not set");