diff --git a/packages/cron/package.json b/packages/cron/package.json index e14c77acce..30e3a927f1 100644 --- a/packages/cron/package.json +++ b/packages/cron/package.json @@ -75,104 +75,7 @@ "browser": true, "node": true }, - "rules": {}, - "overrides": [ - { - "files": [ - "./src/bin/pins-failed.js", - "./src/jobs/dagcargo.js" - ], - "rules": { - "@typescript-eslint/no-unsafe-assignment": "off" - } - }, - { - "files": [ - "./src/jobs/dagcargo.js" - ], - "rules": { - "camelcase": "off" - } - }, - { - "files": [ - "./src/jobs/dagcargo.js", - "./src/jobs/metrics.js", - "./src/jobs/pins.js", - "./src/lib/ipfs.js" - ], - "rules": { - "@typescript-eslint/no-unsafe-member-access": "off" - } - }, - { - "files": [ - "./src/lib/ipfs.js" - ], - "rules": { - "@typescript-eslint/no-unsafe-argument": "off", - "@typescript-eslint/no-unsafe-assignment": "off" - } - }, - { - "files": [ - "./src/lib/fetch.js" - ], - "rules": { - "@typescript-eslint/no-unsafe-assignment": "off" - } - }, - { - "files": [ - "./src/jobs/dagcargo.js", - "./src/jobs/pinata.js", - "./src/jobs/pins.js", - "./src/lib/ipfs.js" - ], - "rules": { - "@typescript-eslint/restrict-template-expressions": "off" - } - }, - { - "files": [ - "./src/jobs/dagcargo.js", - "./src/jobs/pins.js", - "./src/lib/fetch.js", - "./src/lib/pinata.js" - ], - "rules": { - "@typescript-eslint/no-unsafe-return": "off" - } - }, - { - "files": [ - "./src/bin/dagcargo-sizes.js", - "./src/bin/metrics.js", - "./src/bin/pinata.js", - "./src/bin/pins-failed.js", - "./src/bin/pins.js" - ], - "rules": { - "@typescript-eslint/no-floating-promises": "off" - } - }, - { - "files": [ - "./src/bin/dagcargo-sizes.js", - "./src/bin/metrics.js", - "./src/bin/pinata.js", - "./src/bin/pins-failed.js", - "./src/bin/pins.js", - "./src/jobs/dagcargo.js", - "./src/jobs/pinata.js", - "./src/jobs/pins.js", - "./src/lib/pinata.js" - ], - "rules": { - "@typescript-eslint/naming-convention": "off" - } - } - ] + "rules": {} }, "eslintIgnore": [ "node_modules" diff --git a/packages/cron/src/bin/dagcargo-sizes.js b/packages/cron/src/bin/dagcargo-sizes.js index c01abf5349..0b2579da74 100644 --- a/packages/cron/src/bin/dagcargo-sizes.js +++ b/packages/cron/src/bin/dagcargo-sizes.js @@ -22,4 +22,4 @@ async function main() { } dotenv.config({ path: path.join(__dirname, '../../../../.env') }) -main() +await main() diff --git a/packages/cron/src/bin/metrics.js b/packages/cron/src/bin/metrics.js index 0d6548e98b..d98050e485 100755 --- a/packages/cron/src/bin/metrics.js +++ b/packages/cron/src/bin/metrics.js @@ -21,4 +21,4 @@ async function main() { } dotenv.config({ path: path.join(__dirname, '../../../../.env') }) -main() +await main() diff --git a/packages/cron/src/bin/pinata.js b/packages/cron/src/bin/pinata.js index 80865b9b91..dc1f468aa1 100755 --- a/packages/cron/src/bin/pinata.js +++ b/packages/cron/src/bin/pinata.js @@ -16,4 +16,4 @@ async function main() { } dotenv.config({ path: path.join(__dirname, '../../../../.env') }) -main() +await main() diff --git a/packages/cron/src/bin/pins-failed.js b/packages/cron/src/bin/pins-failed.js index f63f701efa..9eb86c320b 100644 --- a/packages/cron/src/bin/pins-failed.js +++ b/packages/cron/src/bin/pins-failed.js @@ -32,4 +32,4 @@ async function main() { } dotenv.config({ path: path.join(__dirname, '../../../../.env') }) -main() +await main() diff --git a/packages/cron/src/bin/pins.js b/packages/cron/src/bin/pins.js index 3e245f5441..9827300433 100755 --- a/packages/cron/src/bin/pins.js +++ b/packages/cron/src/bin/pins.js @@ -26,4 +26,4 @@ async function main() { } dotenv.config({ path: path.join(__dirname, '../../../../.env') }) -main() +await main() diff --git a/packages/cron/src/jobs/dagcargo.js b/packages/cron/src/jobs/dagcargo.js index c65b6a7fbf..c800742e6c 100644 --- a/packages/cron/src/jobs/dagcargo.js +++ b/packages/cron/src/jobs/dagcargo.js @@ -44,6 +44,7 @@ export async function updateDagSizes({ pg, after }) { log(`đŸŽ¯ Updating DAG sizes for content inserted after ${after.toISOString()}`) + /** @type {import('pg').QueryResult<{ count: number }> } */ const countRes = await pg.query(COUNT_CONTENT_WITHOUT_SIZE, [ after.toISOString(), ]) @@ -53,6 +54,7 @@ export async function updateDagSizes({ pg, after }) { let offset = 0 const limit = 1000 while (true) { + /** @type {import('pg').QueryResult<{ cid: string }>} */ const { rows: contents } = await pg.query(FIND_CONTENT_WITHOUT_SIZE, [ after.toISOString(), offset, @@ -61,11 +63,12 @@ export async function updateDagSizes({ pg, after }) { if (!contents.length) break const cids = contents.map((c) => c.cid) + /** @type {import('pg').QueryResult<{ cid_v1: string, size_actual: number }>} */ const { rows: sizes } = await pg.query(FIND_DAG_SIZES, [cids]) - for (const { cid_v1, size_actual } of sizes) { - log(`đŸ’Ē ${cid_v1} ${size_actual} bytes`) - await pg.query(UPDATE_CONTENT_DAG_SIZE, [size_actual, cid_v1]) + for (const s of sizes) { + log(`đŸ’Ē ${s.cid_v1} ${String(s.size_actual)} bytes`) + await pg.query(UPDATE_CONTENT_DAG_SIZE, [s.size_actual, s.cid_v1]) } log(`â„šī¸ ${offset + contents.length} of ${total} processed in total`) diff --git a/packages/cron/src/jobs/metrics.js b/packages/cron/src/jobs/metrics.js index 916d15ef67..7f48d0d589 100644 --- a/packages/cron/src/jobs/metrics.js +++ b/packages/cron/src/jobs/metrics.js @@ -80,6 +80,7 @@ export async function updateMetrics({ roPg, rwPg }) { * @param {Client} rwPg */ async function updateContentRootDagSizeSum(roPg, rwPg) { + /** @type {import('pg').QueryResult<{ total: number }>} */ const { rows } = await roPg.query(SUM_CONTENT_DAG_SIZE) if (!rows.length) throw new Error('no rows returned counting users') await rwPg.query(UPDATE_METRIC, ['content_dag_size_total', rows[0].total]) @@ -90,6 +91,7 @@ async function updateContentRootDagSizeSum(roPg, rwPg) { * @param {Client} rwPg */ async function updateUsersCount(roPg, rwPg) { + /** @type {import('pg').QueryResult<{ total: number }>} */ const { rows } = await roPg.query(COUNT_USERS) if (!rows.length) throw new Error('no rows returned counting users') await rwPg.query(UPDATE_METRIC, ['users_total', rows[0].total]) @@ -100,6 +102,7 @@ async function updateUsersCount(roPg, rwPg) { * @param {Client} rwPg */ async function updateTotalUploadPast7(roPg, rwPg) { + /** @type {import('pg').QueryResult<{ count: number }>} */ const { rows } = await roPg.query(UPLOADS_PAST_7_TOTAL) if (!rows.length) throw new Error('no rows returned counting uploads') await rwPg.query(UPDATE_METRIC, ['uploads_past_7_total', rows[0].count]) @@ -111,6 +114,7 @@ async function updateTotalUploadPast7(roPg, rwPg) { * @param {string} type */ async function updateUploadsCount(roPg, rwPg, type) { + /** @type {import('pg').QueryResult<{ total: number }>} */ const { rows } = await roPg.query(COUNT_UPLOADS, [type]) if (!rows.length) throw new Error(`no rows returned counting ${type} uploads`) await rwPg.query(UPDATE_METRIC, [ @@ -126,6 +130,7 @@ async function updateUploadsCount(roPg, rwPg, type) { * @param {string} status */ async function updatePinsCount(roPg, rwPg, service, status) { + /** @type {import('pg').QueryResult<{ total: number }>} */ const { rows } = await roPg.query(COUNT_PINS, [service, status]) if (!rows.length) throw new Error(`no rows returned counting ${service} ${status} pins`) diff --git a/packages/cron/src/jobs/pinata.js b/packages/cron/src/jobs/pinata.js index df7d530a15..fa580cd6eb 100644 --- a/packages/cron/src/jobs/pinata.js +++ b/packages/cron/src/jobs/pinata.js @@ -33,7 +33,7 @@ export async function pinToPinata({ db, pinata }) { throw Object.assign(new Error(), countError) } - log(`đŸŽ¯ Updating ${count} pin statuses`) + log(`đŸŽ¯ Updating ${count ?? 0} pin statuses`) let offset = 0 const limit = 1000 @@ -91,7 +91,7 @@ export async function pinToPinata({ db, pinata }) { } log(`🗂 ${pins.length} processed, ${updatedPins.length} updated`) - log(`â„šī¸ ${offset + pins.length} of ${count} processed in total`) + log(`â„šī¸ ${offset + pins.length} of ${count ?? 0} processed in total`) offset += limit } diff --git a/packages/cron/src/jobs/pins.js b/packages/cron/src/jobs/pins.js index 5d910a6ab4..d5dcd134e0 100644 --- a/packages/cron/src/jobs/pins.js +++ b/packages/cron/src/jobs/pins.js @@ -47,6 +47,7 @@ export async function updatePendingPinStatuses(config) { * @returns {Promise} */ const countPins = async () => { + /** @type {import('pg').QueryResult<{ count: number }>} */ const { rows } = await config.pg.query(COUNT_PENDING_PINS) if (!rows.length) throw new Error('no rows returned counting pins') return rows[0].count @@ -58,6 +59,7 @@ export async function updatePendingPinStatuses(config) { * @returns {Promise} */ const fetchPins = async (offset, limit) => { + /** @type {import('pg').QueryResult} */ const { rows } = await config.pg.query(FETCH_PENDING_PINS, [offset, limit]) return rows } @@ -98,6 +100,7 @@ export async function checkFailedPinStatuses(config) { * @returns {Promise} */ const countPins = async () => { + /** @type {import('pg').QueryResult<{ count: number }>} */ const { rows } = await pg.query(COUNT_FAILED_PINS, [after.toISOString()]) if (!rows.length) throw new Error('no rows returned counting pins') return rows[0].count @@ -109,6 +112,7 @@ export async function checkFailedPinStatuses(config) { * @returns {Promise} */ const fetchPins = async (offset, limit) => { + /** @type {import('pg').QueryResult} */ const { rows } = await config.pg.query(FETCH_FAILED_PINS, [ after.toISOString(), offset, @@ -129,10 +133,12 @@ function getUpdatePinStatusesSql(pins) { UPDATE pin AS p SET status = c.status, updated_at = c.updated_at - FROM (VALUES ${pins.map( - (p) => - `(${p.id}, '${p.status}'::pin_status_type, '${p.updated_at}'::timestamp)` - )}) AS c(id, status, updated_at) + FROM (VALUES ${pins + .map( + (p) => + `(${p.id}, '${p.status}'::pin_status_type, '${p.updated_at}'::timestamp)` + ) + .join(',')}) AS c(id, status, updated_at) WHERE c.id = p.id`.trim() } diff --git a/packages/cron/src/lib/fetch.js b/packages/cron/src/lib/fetch.js index 4e6e001f4b..0804aed652 100644 --- a/packages/cron/src/lib/fetch.js +++ b/packages/cron/src/lib/fetch.js @@ -13,7 +13,7 @@ const RETRY_ATTEMPTS = 5 * @param {import('limiter').RateLimiter} limiter * @param {string} url * @param {RequestInit} [init] - * @returns {Promise} + * @returns {Promise} */ export async function fetchJSON(limiter, url, init) { await limiter.removeTokens(1) @@ -32,7 +32,7 @@ export async function fetchJSON(limiter, url, init) { { response: res } ) } - return text === '' ? null : JSON.parse(text) + return text === '' ? null : /** @type {unknown} */ (JSON.parse(text)) } finally { clearTimeout(abortID) } diff --git a/packages/cron/src/lib/ipfs.js b/packages/cron/src/lib/ipfs.js index 04ac19ef61..4fbf9595e0 100644 --- a/packages/cron/src/lib/ipfs.js +++ b/packages/cron/src/lib/ipfs.js @@ -1,5 +1,6 @@ import { URL } from 'url' import fetch from '@web-std/fetch' +import { hasOwnProperty } from './utils' export class IPFS { /** @@ -36,10 +37,13 @@ export class IPFS { { response } ) } - const data = await response.json() - const size = parseInt(data.Size) + const data = /** @type {unknown} */ (await response.json()) + if (!hasOwnProperty(data, 'Size')) { + throw new Error('expected response json to have Size') + } + const size = parseInt(String(data.Size)) if (isNaN(size)) { - throw new Error(`invalid DAG size for ${cid}: ${data.Size}`) + throw new Error(`invalid DAG size for ${cid}: ${String(data.Size)}`) } return size } finally { diff --git a/packages/cron/src/lib/pinata.js b/packages/cron/src/lib/pinata.js index 410dc72274..7c33efb209 100644 --- a/packages/cron/src/lib/pinata.js +++ b/packages/cron/src/lib/pinata.js @@ -4,6 +4,14 @@ import { fetchJSON } from './fetch.js' const endpoint = 'https://api.pinata.cloud' +/** + * @typedef PinataPin + * @property {string} id + * @property {string} ipfsHash + * @property {string} status + * @property {string} name + */ + export class Pinata { /** * @param {{ apiToken: string }} config @@ -16,17 +24,21 @@ export class Pinata { /** * @param {string} cid * @param {{ pinataOptions?: { hostNodes?: string[] }, pinataMetadata?: { name?: string } }} [options] - * @returns {Promise<{ id: string, ipfsHash: string, status: string, name: string }>} + * @returns {Promise} */ async pinByHash(cid, options) { const url = new URL('/pinning/pinByHash', endpoint) - return fetchJSON(this.limiter, url.toString(), { - method: 'POST', - headers: { - authorization: `Bearer ${this.apiToken}`, - 'content-type': 'application/json', - }, - body: JSON.stringify({ hashToPin: cid, ...(options || {}) }), - }) + const json = /** @type {unknown} */ ( + await fetchJSON(this.limiter, url.toString(), { + method: 'POST', + headers: { + authorization: `Bearer ${this.apiToken}`, + 'content-type': 'application/json', + }, + body: JSON.stringify({ hashToPin: cid, ...(options || {}) }), + }) + ) + const pin = /** @type {PinataPin} */ (json) + return pin } }