diff --git a/functions/.eslintrc.js b/functions/.eslintrc.js index 5d66d2c6..91ca1cea 100644 --- a/functions/.eslintrc.js +++ b/functions/.eslintrc.js @@ -9,17 +9,27 @@ module.exports = { { files: ['**/*.ts'], plugins: ['@typescript-eslint'], + extends: ['plugin:@typescript-eslint/recommended'], parser: '@typescript-eslint/parser', parserOptions: { tsconfigRootDir: __dirname, project: ['./tsconfig.json'], }, + rules: { + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-extra-semi': 'off', + '@typescript-eslint/no-unused-vars': [ + 'error', + { + argsIgnorePattern: '^_', + varsIgnorePattern: '^_', + caughtErrorsIgnorePattern: '^_', + }, + ], + }, }, ], rules: { - 'no-extra-semi': 'off', - 'no-unused-vars': 'off', - 'no-constant-condition': ['error', { checkLoops: false }], 'lodash/import-scope': [2, 'member'], }, } diff --git a/functions/src/api.ts b/functions/src/api.ts index 36b63692..a305197e 100644 --- a/functions/src/api.ts +++ b/functions/src/api.ts @@ -27,7 +27,6 @@ export class APIError { this.msg = msg this.details = details } - toJson() {} } export const parseCredentials = async (req: Request): Promise => { diff --git a/functions/src/backup-db.ts b/functions/src/backup-db.ts index e840b71a..163760c8 100644 --- a/functions/src/backup-db.ts +++ b/functions/src/backup-db.ts @@ -24,9 +24,12 @@ const bucket = 'gs://manifold-firestore-backup' export const backupDb = functions.pubsub .schedule('every 24 hours') - .onRun((context) => { + .onRun((_context) => { const projectId = process.env.GCP_PROJECT || process.env.GCLOUD_PROJECT - const databaseName = client.databasePath(projectId!, '(default)') + if (projectId == null) { + throw new Error('No project ID environment variable set.') + } + const databaseName = client.databasePath(projectId, '(default)') return client .exportDocuments({ diff --git a/functions/src/call-cloud-function.ts b/functions/src/call-cloud-function.ts index f1e48aa7..35191343 100644 --- a/functions/src/call-cloud-function.ts +++ b/functions/src/call-cloud-function.ts @@ -2,10 +2,10 @@ import * as admin from 'firebase-admin' import fetch from './fetch' -export const callCloudFunction = (functionName: string, data: {} = {}) => { +export const callCloudFunction = (functionName: string, data: unknown = {}) => { const projectId = admin.instanceId().app.options.projectId - let url = `https://us-central1-${projectId}.cloudfunctions.net/${functionName}` + const url = `https://us-central1-${projectId}.cloudfunctions.net/${functionName}` return fetch(url, { method: 'POST', diff --git a/functions/src/create-fold.ts b/functions/src/create-fold.ts index 2d808673..d6a33188 100644 --- a/functions/src/create-fold.ts +++ b/functions/src/create-fold.ts @@ -22,17 +22,18 @@ export const createFold = functions.runWith({ minInstances: 1 }).https.onCall( const creator = await getUser(userId) if (!creator) return { status: 'error', message: 'User not found' } - let { name, about, tags } = data + let { name, about } = data if (!name || typeof name !== 'string') return { status: 'error', message: 'Name must be a non-empty string' } - name = name.trim().slice(0, 140) if (typeof about !== 'string') return { status: 'error', message: 'About must be a string' } about = about.trim().slice(0, 140) + const { tags } = data + if (!Array.isArray(tags)) return { status: 'error', message: 'Tags must be an array of strings' } diff --git a/functions/src/create-notification.ts b/functions/src/create-notification.ts index bd77f690..fc5e606d 100644 --- a/functions/src/create-notification.ts +++ b/functions/src/create-notification.ts @@ -72,7 +72,7 @@ export const createNotification = async ( sourceType === 'answer' || sourceType === 'contract' ) { - let reasonTextPretext = getReasonTextFromReason(sourceType, reason) + const reasonTextPretext = getReasonTextFromReason(sourceType, reason) const notifyContractCreator = async ( userToReasonTexts: user_to_reason_texts diff --git a/functions/src/emails.ts b/functions/src/emails.ts index 61fded50..2f484f36 100644 --- a/functions/src/emails.ts +++ b/functions/src/emails.ts @@ -3,7 +3,7 @@ import { Answer } from '../../common/answer' import { Bet } from '../../common/bet' import { getProbability } from '../../common/calculate' import { Comment } from '../../common/comment' -import { Contract, FreeResponseContract } from '../../common/contract' +import { Contract } from '../../common/contract' import { DPM_CREATOR_FEE } from '../../common/fees' import { PrivateUser, User } from '../../common/user' import { formatMoney, formatPercent } from '../../common/util/format' diff --git a/functions/src/market-close-emails.ts b/functions/src/market-close-emails.ts index bb144600..382751f6 100644 --- a/functions/src/market-close-emails.ts +++ b/functions/src/market-close-emails.ts @@ -40,7 +40,7 @@ async function sendMarketCloseEmails() { .filter((x) => !!x) as Contract[] }) - for (let contract of contracts) { + for (const contract of contracts) { console.log( 'sending close email for', contract.slug, diff --git a/functions/src/on-fold-delete.ts b/functions/src/on-fold-delete.ts index 7762e113..10afca43 100644 --- a/functions/src/on-fold-delete.ts +++ b/functions/src/on-fold-delete.ts @@ -2,7 +2,7 @@ import * as functions from 'firebase-functions' export const onFoldDelete = functions.firestore .document('folds/{foldId}') - .onDelete(async (change, context) => { + .onDelete(async (change, _context) => { const snapshot = await change.ref.collection('followers').get() // Delete followers sub-collection. diff --git a/functions/src/scripts/cache-views.ts b/functions/src/scripts/cache-views.ts index dc54bdf9..44ceb89a 100644 --- a/functions/src/scripts/cache-views.ts +++ b/functions/src/scripts/cache-views.ts @@ -52,25 +52,25 @@ async function cacheUserViews(userId: string) { console.log(viewCounts, lastViewTime) } -async function deleteCache() { - console.log('Deleting view cache') +// async function deleteCache() { +// console.log('Deleting view cache') - const users = await getValues(firestore.collection('users')) +// const users = await getValues(firestore.collection('users')) - await batchedWaitAll( - users.map((user) => async () => { - console.log('Deleting view cache for', user.username) - await firestore.doc(`private-users/${user.id}/cache/viewCounts`).delete() - await firestore - .doc(`private-users/${user.id}/cache/lastViewTime`) - .delete() - await firestore - .doc(`private-users/${user.id}/cache/contractScores`) - .delete() - await firestore.doc(`private-users/${user.id}/cache/wordScores`).delete() - }) - ) -} +// await batchedWaitAll( +// users.map((user) => async () => { +// console.log('Deleting view cache for', user.username) +// await firestore.doc(`private-users/${user.id}/cache/viewCounts`).delete() +// await firestore +// .doc(`private-users/${user.id}/cache/lastViewTime`) +// .delete() +// await firestore +// .doc(`private-users/${user.id}/cache/contractScores`) +// .delete() +// await firestore.doc(`private-users/${user.id}/cache/wordScores`).delete() +// }) +// ) +// } if (require.main === module) { cacheViews().then(() => process.exit()) diff --git a/functions/src/scripts/change-user-info.ts b/functions/src/scripts/change-user-info.ts index 64858c46..65f5317f 100644 --- a/functions/src/scripts/change-user-info.ts +++ b/functions/src/scripts/change-user-info.ts @@ -1,5 +1,3 @@ -import * as admin from 'firebase-admin' - import { initAdmin } from './script-init' initAdmin() diff --git a/functions/src/scripts/create-private-users.ts b/functions/src/scripts/create-private-users.ts index 37168a39..9b0c4096 100644 --- a/functions/src/scripts/create-private-users.ts +++ b/functions/src/scripts/create-private-users.ts @@ -11,7 +11,7 @@ async function main() { const snap = await firestore.collection('users').get() const users = snap.docs.map((d) => d.data() as User) - for (let user of users) { + for (const user of users) { const fbUser = await admin.auth().getUser(user.id) const email = fbUser.email const { username } = user diff --git a/functions/src/scripts/denormalize.ts b/functions/src/scripts/denormalize.ts index ca4111b0..20bfc458 100644 --- a/functions/src/scripts/denormalize.ts +++ b/functions/src/scripts/denormalize.ts @@ -6,7 +6,7 @@ import { DocumentSnapshot, Transaction } from 'firebase-admin/firestore' export type DocumentValue = { doc: DocumentSnapshot field: string - val: any + val: unknown } export type DocumentCorrespondence = [DocumentSnapshot, DocumentSnapshot[]] export type DocumentDiff = { @@ -20,9 +20,9 @@ export function findDiffs( destPath: string ) { const diffs: DocumentDiff[] = [] - for (let [srcDoc, destDocs] of docs) { + for (const [srcDoc, destDocs] of docs) { const srcVal = srcDoc.get(srcPath) - for (let destDoc of destDocs) { + for (const destDoc of destDocs) { const destVal = destDoc.get(destPath) if (destVal !== srcVal) { diffs.push({ diff --git a/functions/src/scripts/migrate-contract.ts b/functions/src/scripts/migrate-contract.ts index b3ed6025..acfdd41e 100644 --- a/functions/src/scripts/migrate-contract.ts +++ b/functions/src/scripts/migrate-contract.ts @@ -18,7 +18,7 @@ async function migrateBet(contractRef: DocRef, bet: Bet) { await contractRef.collection('bets').doc(id).update({ shares }) } -async function migrateContract(contractRef: DocRef, contract: Contract) { +async function migrateContract(contractRef: DocRef) { const bets = await contractRef .collection('bets') .get() @@ -48,7 +48,7 @@ async function migrateContracts() { console.log('contract', contract.question, 'bets', bets.length) for (const bet of bets) await migrateBet(contractRef, bet) - await migrateContract(contractRef, contract) + await migrateContract(contractRef) } } diff --git a/functions/src/scripts/migrate-to-cfmm.ts b/functions/src/scripts/migrate-to-cfmm.ts index 039b04be..503dbfdf 100644 --- a/functions/src/scripts/migrate-to-cfmm.ts +++ b/functions/src/scripts/migrate-to-cfmm.ts @@ -57,7 +57,7 @@ async function recalculateContract(contractRef: DocRef, isCommit = false) { : 0 } - for (let bet of bets) { + for (const bet of bets) { const shares = bet.sale ? getSoldBetPayout(bet) : bet.isSold @@ -139,7 +139,7 @@ async function main() { !snap.empty ? [firestore.doc(`contracts/${snap.docs[0].id}`)] : [] ) - for (let contractRef of contractRefs) { + for (const contractRef of contractRefs) { await recalculateContract(contractRef, isCommit).catch((e) => console.log('error: ', e, 'id=', contractRef.id) ) diff --git a/functions/src/scripts/migrate-to-dpm-2.ts b/functions/src/scripts/migrate-to-dpm-2.ts index ffbd1ef2..98e2f9fc 100644 --- a/functions/src/scripts/migrate-to-dpm-2.ts +++ b/functions/src/scripts/migrate-to-dpm-2.ts @@ -100,7 +100,7 @@ async function recalculateContract( console.log('start', { pool, totalBets, totalShares }) - for (let bet of bets) { + for (const bet of bets) { if (bet.sale) { const soldBet = bets.find((b) => b.id === bet.sale?.betId) if (!soldBet) throw new Error('invalid sold bet' + bet.sale.betId) diff --git a/functions/src/scripts/script-init.ts b/functions/src/scripts/script-init.ts index d3acbc66..8f65e4be 100644 --- a/functions/src/scripts/script-init.ts +++ b/functions/src/scripts/script-init.ts @@ -64,6 +64,7 @@ export const initAdmin = (env?: string) => { return } console.log(`Initializing connection to ${env} Firebase...`) + /* eslint-disable-next-line @typescript-eslint/no-var-requires */ const serviceAccount = require(keyPath) admin.initializeApp({ credential: admin.credential.cert(serviceAccount), diff --git a/functions/src/sell-bet.ts b/functions/src/sell-bet.ts index 3ef5a094..93fcb6a2 100644 --- a/functions/src/sell-bet.ts +++ b/functions/src/sell-bet.ts @@ -6,7 +6,6 @@ import { User } from '../../common/user' import { Bet } from '../../common/bet' import { getSellBetInfo } from '../../common/sell-bet' import { addObjects, removeUndefinedProps } from '../../common/util/object' -import { Fees } from '../../common/fees' export const sellBet = functions.runWith({ minInstances: 1 }).https.onCall( async ( @@ -50,7 +49,8 @@ export const sellBet = functions.runWith({ minInstances: 1 }).https.onCall( if (!betSnap.exists) return { status: 'error', message: 'Invalid bet' } const bet = betSnap.data() as Bet - if (userId !== bet.userId) return { status: 'error', message: 'Not authorized' } + if (userId !== bet.userId) + return { status: 'error', message: 'Not authorized' } if (bet.isSold) return { status: 'error', message: 'Bet already sold' } const newBetDoc = firestore diff --git a/functions/src/unsubscribe.ts b/functions/src/unsubscribe.ts index baea8022..a41a7155 100644 --- a/functions/src/unsubscribe.ts +++ b/functions/src/unsubscribe.ts @@ -6,7 +6,8 @@ import { PrivateUser } from '../../common/user' export const unsubscribe = functions .runWith({ minInstances: 1 }) .https.onRequest(async (req, res) => { - let { id, type } = req.query as { id: string; type: string } + const id = req.query.id as string + let type = req.query.type as string if (!id || !type) { res.status(400).send('Empty id or type parameter.') return diff --git a/functions/src/update-feed.ts b/functions/src/update-feed.ts index 104473c1..03b1666c 100644 --- a/functions/src/update-feed.ts +++ b/functions/src/update-feed.ts @@ -31,7 +31,7 @@ const MAX_BATCHES = 50 const getUserBatches = async () => { const users = shuffle(await getValues(firestore.collection('users'))) - let userBatches: User[][] = [] + const userBatches: User[][] = [] for (let i = 0; i < users.length; i += BATCH_SIZE) { userBatches.push(users.slice(i, i + BATCH_SIZE)) } @@ -197,18 +197,18 @@ function getActivityScore(contract: Contract, viewTime: number | undefined) { return isNew ? newMappedScore : mappedScore } -function getLastViewedScore(viewTime: number | undefined) { - if (viewTime === undefined) { - return 1 - } +// function getLastViewedScore(viewTime: number | undefined) { +// if (viewTime === undefined) { +// return 1 +// } - const daysAgo = (Date.now() - viewTime) / DAY_MS +// const daysAgo = (Date.now() - viewTime) / DAY_MS - if (daysAgo < 0.5) { - const frac = logInterpolation(0, 0.5, daysAgo) - return 0.5 + 0.25 * frac - } +// if (daysAgo < 0.5) { +// const frac = logInterpolation(0, 0.5, daysAgo) +// return 0.5 + 0.25 * frac +// } - const frac = logInterpolation(0.5, 14, daysAgo) - return 0.75 + 0.25 * frac -} +// const frac = logInterpolation(0.5, 14, daysAgo) +// return 0.75 + 0.25 * frac +// } diff --git a/functions/src/update-user-metrics.ts b/functions/src/update-user-metrics.ts index 08dc63e6..0ab7cd8c 100644 --- a/functions/src/update-user-metrics.ts +++ b/functions/src/update-user-metrics.ts @@ -71,9 +71,9 @@ const computeTotalPool = async ( return sum(pools) } -const computeVolume = async (contract: Contract) => { - const bets = await getValues( - firestore.collection(`contracts/${contract.id}/bets`) - ) - return sumBy(bets, (bet) => Math.abs(bet.amount)) -} +// const computeVolume = async (contract: Contract) => { +// const bets = await getValues( +// firestore.collection(`contracts/${contract.id}/bets`) +// ) +// return sumBy(bets, (bet) => Math.abs(bet.amount)) +// }