From 73375588a88d24d8e2eae681ebc2b1404c4d00b8 Mon Sep 17 00:00:00 2001 From: derekvmcintire Date: Sat, 21 Dec 2024 18:01:24 -0500 Subject: [PATCH 1/3] fixed all ts errors and lint warnings --- .../EnergyUseHistoryChart.tsx | 3 +- heat-stack/app/components/ui/table.tsx | 3 +- .../routes/_auth+/onboarding_.$provider.tsx | 4 +-- heat-stack/app/routes/_heat+/single.tsx | 4 +-- heat-stack/app/routes/admin+/cache.tsx | 2 +- .../app/routes/admin+/cache_.sqlite.server.ts | 2 +- .../settings+/profile.change-email.server.tsx | 2 +- .../$username_+/__note-editor.server.tsx | 2 +- .../users+/$username_+/__note-editor.tsx | 2 +- .../app/utils/misc.use-double-check.test.tsx | 28 +++++++++---------- .../app/utils/providers/github.server.ts | 11 ++++---- heat-stack/app/utils/pyodide.test.ts | 4 +-- heat-stack/prisma/seed.ts | 2 +- heat-stack/server/index.ts | 6 ++-- heat-stack/tailwind.config.ts | 2 +- heat-stack/tests/e2e/onboarding.test.ts | 4 +-- heat-stack/tsconfig.json | 26 +++++++++-------- heat-stack/types/vite-env-only.d.ts | 1 + 18 files changed, 56 insertions(+), 52 deletions(-) create mode 100644 heat-stack/types/vite-env-only.d.ts diff --git a/heat-stack/app/components/ui/heat/CaseSummaryComponents/EnergyUseHistoryChart.tsx b/heat-stack/app/components/ui/heat/CaseSummaryComponents/EnergyUseHistoryChart.tsx index 40e3c51c..5061289a 100644 --- a/heat-stack/app/components/ui/heat/CaseSummaryComponents/EnergyUseHistoryChart.tsx +++ b/heat-stack/app/components/ui/heat/CaseSummaryComponents/EnergyUseHistoryChart.tsx @@ -1,3 +1,4 @@ +import { tr } from '@faker-js/faker' import { useState, useEffect } from 'react' import { type z } from 'zod' import { type UsageDataSchema, type BillingRecordsSchema } from '#/types/types.ts' @@ -17,8 +18,6 @@ import HelpCircle from './assets/help-circle.svg' import NonHeatingUsage from './assets/NonHeatingUsage.svg' import NotAllowedInCalculations from './assets/NotAllowedInCalculations.svg' -import { tr } from '@faker-js/faker' - // type NaturalGasBillRecord = z.infer // const naturalGasBillRecord01: NaturalGasBillRecord = { // periodStartDate: new Date('12/08/2017'), diff --git a/heat-stack/app/components/ui/table.tsx b/heat-stack/app/components/ui/table.tsx index 364d0050..7ff26bfe 100644 --- a/heat-stack/app/components/ui/table.tsx +++ b/heat-stack/app/components/ui/table.tsx @@ -1,7 +1,8 @@ +import { cva, type VariantProps } from 'class-variance-authority' import * as React from 'react' import { cn } from '#app/utils/misc.tsx' -import { cva, VariantProps } from 'class-variance-authority' + const Table = React.forwardRef< HTMLTableElement, diff --git a/heat-stack/app/routes/_auth+/onboarding_.$provider.tsx b/heat-stack/app/routes/_auth+/onboarding_.$provider.tsx index 9cbdc51a..c8fc97ce 100644 --- a/heat-stack/app/routes/_auth+/onboarding_.$provider.tsx +++ b/heat-stack/app/routes/_auth+/onboarding_.$provider.tsx @@ -30,7 +30,7 @@ import { signupWithConnection, requireAnonymous, } from '#app/utils/auth.server.ts' -import { connectionSessionStorage } from '#app/utils/connections.server' +import { connectionSessionStorage } from '#app/utils/connections.server.ts' import { ProviderNameSchema } from '#app/utils/connections.tsx' import { prisma } from '#app/utils/db.server.ts' import { useIsPending } from '#app/utils/misc.tsx' @@ -38,7 +38,7 @@ import { authSessionStorage } from '#app/utils/session.server.ts' import { redirectWithToast } from '#app/utils/toast.server.ts' import { NameSchema, UsernameSchema } from '#app/utils/user-validation.ts' import { verifySessionStorage } from '#app/utils/verification.server.ts' -import { onboardingEmailSessionKey } from './onboarding' +import { onboardingEmailSessionKey } from './onboarding.tsx' export const providerIdKey = 'providerId' export const prefilledProfileKey = 'prefilledProfile' diff --git a/heat-stack/app/routes/_heat+/single.tsx b/heat-stack/app/routes/_heat+/single.tsx index 25be9d32..16e1bbbc 100644 --- a/heat-stack/app/routes/_heat+/single.tsx +++ b/heat-stack/app/routes/_heat+/single.tsx @@ -11,8 +11,8 @@ import * as pyodideModule from 'pyodide' import { type z } from 'zod' import { Button } from '#/app/components/ui/button.tsx' import { ErrorList } from '#app/components/ui/heat/CaseSummaryComponents/ErrorList.tsx' -import GeocodeUtil from '#app/utils/GeocodeUtil' -import WeatherUtil from '#app/utils/WeatherUtil' +import GeocodeUtil from '#app/utils/GeocodeUtil.ts' +import WeatherUtil from '#app/utils/WeatherUtil.ts' diff --git a/heat-stack/app/routes/admin+/cache.tsx b/heat-stack/app/routes/admin+/cache.tsx index 741e8584..7fe17f94 100644 --- a/heat-stack/app/routes/admin+/cache.tsx +++ b/heat-stack/app/routes/admin+/cache.tsx @@ -14,7 +14,7 @@ import { useSearchParams, useSubmit, } from '@remix-run/react' -import { GeneralErrorBoundary } from '#app/components/error-boundary' +import { GeneralErrorBoundary } from '#app/components/error-boundary.tsx' import { Field } from '#app/components/forms.tsx' import { Spacer } from '#app/components/spacer.tsx' import { Button } from '#app/components/ui/button.tsx' diff --git a/heat-stack/app/routes/admin+/cache_.sqlite.server.ts b/heat-stack/app/routes/admin+/cache_.sqlite.server.ts index a9c8f80e..a44eb1be 100644 --- a/heat-stack/app/routes/admin+/cache_.sqlite.server.ts +++ b/heat-stack/app/routes/admin+/cache_.sqlite.server.ts @@ -4,7 +4,7 @@ import { cache } from '#app/utils/cache.server.ts' import { getInstanceInfo, getInternalInstanceDomain, -} from '#app/utils/litefs.server' +} from '#app/utils/litefs.server.ts' export async function updatePrimaryCacheValue({ key, diff --git a/heat-stack/app/routes/settings+/profile.change-email.server.tsx b/heat-stack/app/routes/settings+/profile.change-email.server.tsx index 0a0eebc0..a36f9456 100644 --- a/heat-stack/app/routes/settings+/profile.change-email.server.tsx +++ b/heat-stack/app/routes/settings+/profile.change-email.server.tsx @@ -9,7 +9,7 @@ import { prisma } from '#app/utils/db.server.ts' import { sendEmail } from '#app/utils/email.server.ts' import { redirectWithToast } from '#app/utils/toast.server.ts' import { verifySessionStorage } from '#app/utils/verification.server.ts' -import { newEmailAddressSessionKey } from './profile.change-email' +import { newEmailAddressSessionKey } from './profile.change-email.tsx' export async function handleVerification({ request, diff --git a/heat-stack/app/routes/users+/$username_+/__note-editor.server.tsx b/heat-stack/app/routes/users+/$username_+/__note-editor.server.tsx index 8b1796ce..c336950c 100644 --- a/heat-stack/app/routes/users+/$username_+/__note-editor.server.tsx +++ b/heat-stack/app/routes/users+/$username_+/__note-editor.server.tsx @@ -14,7 +14,7 @@ import { MAX_UPLOAD_SIZE, NoteEditorSchema, type ImageFieldset, -} from './__note-editor' +} from './__note-editor.tsx' function imageHasFile( image: ImageFieldset, diff --git a/heat-stack/app/routes/users+/$username_+/__note-editor.tsx b/heat-stack/app/routes/users+/$username_+/__note-editor.tsx index a5ab1305..cd3e9ccb 100644 --- a/heat-stack/app/routes/users+/$username_+/__note-editor.tsx +++ b/heat-stack/app/routes/users+/$username_+/__note-editor.tsx @@ -22,7 +22,7 @@ import { Label } from '#app/components/ui/label.tsx' import { StatusButton } from '#app/components/ui/status-button.tsx' import { Textarea } from '#app/components/ui/textarea.tsx' import { cn, getNoteImgSrc, useIsPending } from '#app/utils/misc.tsx' -import { type action } from './__note-editor.server' +import { type action } from './__note-editor.server.tsx' const titleMinLength = 1 const titleMaxLength = 100 diff --git a/heat-stack/app/utils/misc.use-double-check.test.tsx b/heat-stack/app/utils/misc.use-double-check.test.tsx index 4adfa593..0db59ec9 100644 --- a/heat-stack/app/utils/misc.use-double-check.test.tsx +++ b/heat-stack/app/utils/misc.use-double-check.test.tsx @@ -34,16 +34,16 @@ test('prevents default on the first click, and does not on the second', async () const status = screen.getByRole('status') const button = screen.getByRole('button') - expect(status).toHaveTextContent('Default Prevented: idle') - expect(button).toHaveTextContent('Click me') + expect(status.textContent).toBe('Default Prevented: idle') + expect(button.textContent).toBe('Click me') await user.click(button) - expect(button).toHaveTextContent('You sure?') - expect(status).toHaveTextContent('Default Prevented: yes') + expect(button.textContent).toBe('You sure?') + expect(status.textContent).toBe('Default Prevented: yes') await user.click(button) - expect(button).toHaveTextContent('You sure?') - expect(status).toHaveTextContent('Default Prevented: no') + expect(button.textContent).toBe('You sure?') + expect(status.textContent).toBe('Default Prevented: no') }) test('blurring the button starts things over', async () => { @@ -54,14 +54,14 @@ test('blurring the button starts things over', async () => { const button = screen.getByRole('button') await user.click(button) - expect(button).toHaveTextContent('You sure?') - expect(status).toHaveTextContent('Default Prevented: yes') + expect(button.textContent).toBe('You sure?') + expect(status.textContent).toBe('Default Prevented: yes') await user.click(document.body) // button goes back to click me - expect(button).toHaveTextContent('Click me') + expect(button.textContent).toBe('Click me') // our callback wasn't called, so the status doesn't change - expect(status).toHaveTextContent('Default Prevented: yes') + expect(status.textContent).toBe('Default Prevented: yes') }) test('hitting "escape" on the input starts things over', async () => { @@ -72,12 +72,12 @@ test('hitting "escape" on the input starts things over', async () => { const button = screen.getByRole('button') await user.click(button) - expect(button).toHaveTextContent('You sure?') - expect(status).toHaveTextContent('Default Prevented: yes') + expect(button.textContent).toBe('You sure?') + expect(status.textContent).toBe('Default Prevented: yes') await user.keyboard('{Escape}') // button goes back to click me - expect(button).toHaveTextContent('Click me') + expect(button.textContent).toBe('Click me') // our callback wasn't called, so the status doesn't change - expect(status).toHaveTextContent('Default Prevented: yes') + expect(status.textContent).toBe('Default Prevented: yes') }) diff --git a/heat-stack/app/utils/providers/github.server.ts b/heat-stack/app/utils/providers/github.server.ts index 895271bb..49aff9a8 100644 --- a/heat-stack/app/utils/providers/github.server.ts +++ b/heat-stack/app/utils/providers/github.server.ts @@ -1,12 +1,13 @@ import { createId as cuid } from '@paralleldrive/cuid2' import { redirect } from '@remix-run/node' -import { GitHubStrategy } from 'remix-auth-github' +import { type Strategy } from 'remix-auth' +import { GitHubStrategy, type GitHubStrategyOptions } from 'remix-auth-github' import { z } from 'zod' import { cache, cachified } from '../cache.server.ts' import { connectionSessionStorage } from '../connections.server.ts' import { type Timings } from '../timing.server.ts' import { MOCK_CODE_GITHUB_HEADER, MOCK_CODE_GITHUB } from './constants.ts' -import { type AuthProvider } from './provider.ts' +import { type ProviderUser, type AuthProvider } from './provider.ts' const GitHubUserSchema = z.object({ login: z.string() }) const GitHubUserParseResult = z @@ -25,20 +26,20 @@ const shouldMock = process.env.NODE_ENV === 'test' export class GitHubProvider implements AuthProvider { - getAuthStrategy() { + getAuthStrategy(): Strategy { // @TODO double check the types here return new GitHubStrategy( { clientID: process.env.GITHUB_CLIENT_ID, clientSecret: process.env.GITHUB_CLIENT_SECRET, callbackURL: '/auth/github/callback', - }, + } as unknown as GitHubStrategyOptions, // @TODO fix types here, clientID and callbackURL do not exist on GitHubStrategyOptions async ({ profile }) => { const email = profile.emails[0]?.value.trim().toLowerCase() if (!email) { throw new Error('Email not found') } const username = profile.displayName - const imageUrl = profile.photos[0].value + const imageUrl = profile.photos?.[0]?.value || ''; return { email, id: profile.id, diff --git a/heat-stack/app/utils/pyodide.test.ts b/heat-stack/app/utils/pyodide.test.ts index 197fce8a..7a2543df 100644 --- a/heat-stack/app/utils/pyodide.test.ts +++ b/heat-stack/app/utils/pyodide.test.ts @@ -1,7 +1,7 @@ import * as pyodideModule from 'pyodide' import { expect, test, beforeEach } from 'vitest' -import GeocodeUtil from "#app/utils/GeocodeUtil"; -import WeatherUtil from "#app/utils/WeatherUtil"; +import GeocodeUtil from "#app/utils/GeocodeUtil.ts"; +import WeatherUtil from "#app/utils/WeatherUtil.ts"; // import PyodideUtil from "#app/utils/pyodide.util.js"; diff --git a/heat-stack/prisma/seed.ts b/heat-stack/prisma/seed.ts index 9f29df1f..52fb4d0b 100644 --- a/heat-stack/prisma/seed.ts +++ b/heat-stack/prisma/seed.ts @@ -1,7 +1,7 @@ import { faker } from '@faker-js/faker' import { promiseHash } from 'remix-utils/promise' import { prisma } from '#app/utils/db.server.ts' -import { MOCK_CODE_GITHUB } from '#app/utils/providers/constants' +import { MOCK_CODE_GITHUB } from '#app/utils/providers/constants.ts' import { cleanupDb, createPassword, diff --git a/heat-stack/server/index.ts b/heat-stack/server/index.ts index 036e61dc..a31c4511 100644 --- a/heat-stack/server/index.ts +++ b/heat-stack/server/index.ts @@ -115,7 +115,7 @@ app.use( MODE === 'development' ? 'ws:' : null, process.env.SENTRY_DSN ? '*.sentry.io' : null, "'self'", - ].filter(Boolean), + ].filter(Boolean) as string[], 'font-src': ["'self'"], 'frame-src': ["'self'"], 'img-src': ["'self'", 'data:'], @@ -201,8 +201,8 @@ async function getBuild() { try { const build = viteDevServer ? await viteDevServer.ssrLoadModule('virtual:remix/server-build') - : // @ts-expect-error - the file might not exist yet but it will - // eslint-disable-next-line import/no-unresolved + : // @ ts-expect-error - the file might not exist yet but it will + // e slint-disable-next-line import/no-unresolved await import('../build/server/index.js') return { build: build as unknown as ServerBuild, error: null } diff --git a/heat-stack/tailwind.config.ts b/heat-stack/tailwind.config.ts index 0c4695b3..d678a3c8 100644 --- a/heat-stack/tailwind.config.ts +++ b/heat-stack/tailwind.config.ts @@ -1,7 +1,7 @@ import { type Config } from 'tailwindcss' import animatePlugin from 'tailwindcss-animate' import radixPlugin from 'tailwindcss-radix' -import { marketingPreset } from './app/routes/_marketing+/tailwind-preset' +import { marketingPreset } from './app/routes/_marketing+/tailwind-preset.ts' import { extendedTheme } from './app/utils/extended-theme.ts' export default { diff --git a/heat-stack/tests/e2e/onboarding.test.ts b/heat-stack/tests/e2e/onboarding.test.ts index 92064e3f..6bea9da3 100644 --- a/heat-stack/tests/e2e/onboarding.test.ts +++ b/heat-stack/tests/e2e/onboarding.test.ts @@ -4,11 +4,11 @@ import { prisma } from '#app/utils/db.server.ts' import { normalizeEmail, normalizeUsername, -} from '#app/utils/providers/provider' +} from '#app/utils/providers/provider.ts' import { USERNAME_MAX_LENGTH, USERNAME_MIN_LENGTH, -} from '#app/utils/user-validation' +} from '#app/utils/user-validation.ts' import { readEmail } from '#tests/mocks/utils.ts' import { createUser, expect, test as base } from '#tests/playwright-utils.ts' diff --git a/heat-stack/tsconfig.json b/heat-stack/tsconfig.json index a15dcc7e..66116b8b 100644 --- a/heat-stack/tsconfig.json +++ b/heat-stack/tsconfig.json @@ -2,18 +2,20 @@ "include": ["**/*.ts", "**/*.tsx"], "extends": ["@epic-web/config/typescript"], "compilerOptions": { - // "lib": ["DOM", "DOM.Iterable", "ES2022"], - // "isolatedModules": true, - // "esModuleInterop": true, - // "jsx": "react-jsx", - // "module": "ES2022", - // "target": "ES2022", - // "moduleResolution": "bundler", - // "resolveJsonModule": true, - // "strict": true, - // "noImplicitAny": true, - // "allowJs": true, - // "forceConsistentCasingInFileNames": true, + "target": "ES2018", + "lib": ["DOM", "DOM.Iterable", "ESNext"], + "allowJs": true, + "skipLibCheck": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "module": "NodeNext", + "moduleResolution": "nodenext", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", "paths": { "#*": ["./*"], "#app/*": ["./app/*"], diff --git a/heat-stack/types/vite-env-only.d.ts b/heat-stack/types/vite-env-only.d.ts new file mode 100644 index 00000000..9c6da43a --- /dev/null +++ b/heat-stack/types/vite-env-only.d.ts @@ -0,0 +1 @@ +declare module 'vite-env-only'; From 3be08f1886d9f9a172ba76b43c0f1af71b2b4f40 Mon Sep 17 00:00:00 2001 From: derekvmcintire Date: Thu, 9 Jan 2025 16:49:28 -0500 Subject: [PATCH 2/3] Add comments to tsconfig --- heat-stack/tsconfig.json | 49 +++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/heat-stack/tsconfig.json b/heat-stack/tsconfig.json index 66116b8b..8536dd80 100644 --- a/heat-stack/tsconfig.json +++ b/heat-stack/tsconfig.json @@ -1,32 +1,29 @@ { - "include": ["**/*.ts", "**/*.tsx"], - "extends": ["@epic-web/config/typescript"], + "include": ["**/*.ts", "**/*.tsx"], //Include all TypeScript (.ts) and TypeScript with JSX (.tsx) files in the project directory and its subdirectories. + "extends": ["@epic-web/config/typescript"], // Uses a shared TypeScript configuration provided by the @epic-web package as the base. "compilerOptions": { - "target": "ES2018", - "lib": ["DOM", "DOM.Iterable", "ESNext"], - "allowJs": true, - "skipLibCheck": true, - "esModuleInterop": true, - "allowSyntheticDefaultImports": true, - "strict": true, - "forceConsistentCasingInFileNames": true, - "module": "NodeNext", - "moduleResolution": "nodenext", - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true, - "jsx": "react-jsx", - "paths": { - "#*": ["./*"], - "#app/*": ["./app/*"], - "#tests/*": ["./tests/*"], - "@/icon-name": [ - "./app/components/ui/icons/name.d.ts", - "./types/icon-name.d.ts" + "target": "ES2018", // Compile TypeScript code to ECMAScript 2018. + "lib": ["DOM", "DOM.Iterable", "ESNext"], // Includes type definitions for the DOM, DOM iterables, and modern ECMAScript features. + "allowJs": true, // Enables the inclusion of .js files in the project. + "skipLibCheck": true, // Skip type checking of all declaration files (*.d.ts). + "esModuleInterop": true, // Enables compatibility with CommonJS modules. + "allowSyntheticDefaultImports": true, // Allows default imports from modules with no default export. + "strict": true, // Enables all strict type-checking options. + "forceConsistentCasingInFileNames": true, // Enforces a consistent casing in file names. + "module": "NodeNext", // Uses Node.js-style ES Module resolution for compatibility with modern Node.js versions. + "moduleResolution": "nodenext", // Uses Node.js ES Module resolution logic. + "resolveJsonModule": true, // Allows importing JSON files as modules. + "isolatedModules": true, // Disallows the use of global modules and global side-effects. + "noEmit": true, // Disables emitting output files. + "jsx": "react-jsx", // Enables JSX support with React JSX. + "paths": { // Maps paths to different directories or files. + "#*": ["./*"], // Maps all paths starting with # to the root directory. + "#app/*": ["./app/*"], // Maps all paths starting with #app to the app directory. + "#tests/*": ["./tests/*"], // Maps all paths starting with #tests to the tests directory. + "@/icon-name": [ // Maps the @/icon-name path to the icon-name.d.ts file. + "./app/components/ui/icons/name.d.ts", // Maps the @/icon-name path to the + "./types/icon-name.d.ts" // icon-name.d.ts file in the types directory. ] } - // ,"skipLibCheck": true, - // "allowImportingTsExtensions": true, - // "noEmit": true, } } From 02278734fdf6d4f6dbff1f734c1780c7b4dd6ad7 Mon Sep 17 00:00:00 2001 From: derekvmcintire Date: Thu, 9 Jan 2025 17:01:58 -0500 Subject: [PATCH 3/3] Don't override includes --- heat-stack/tsconfig.json | 1 - 1 file changed, 1 deletion(-) diff --git a/heat-stack/tsconfig.json b/heat-stack/tsconfig.json index 8536dd80..912809b9 100644 --- a/heat-stack/tsconfig.json +++ b/heat-stack/tsconfig.json @@ -1,5 +1,4 @@ { - "include": ["**/*.ts", "**/*.tsx"], //Include all TypeScript (.ts) and TypeScript with JSX (.tsx) files in the project directory and its subdirectories. "extends": ["@epic-web/config/typescript"], // Uses a shared TypeScript configuration provided by the @epic-web package as the base. "compilerOptions": { "target": "ES2018", // Compile TypeScript code to ECMAScript 2018.