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/heat/CaseSummaryComponents/Graphs/HeatLoad.tsx b/heat-stack/app/components/ui/heat/CaseSummaryComponents/Graphs/HeatLoad.tsx index fc77291a..b32d0029 100644 --- a/heat-stack/app/components/ui/heat/CaseSummaryComponents/Graphs/HeatLoad.tsx +++ b/heat-stack/app/components/ui/heat/CaseSummaryComponents/Graphs/HeatLoad.tsx @@ -1,4 +1,4 @@ -import React, { useMemo } from 'react' +import { useMemo } from 'react' import { ComposedChart, Line, @@ -10,22 +10,22 @@ import { Label, Scatter, } from 'recharts' -import { SummaryOutputSchema } from '../../../../../../types/types' -import { Icon } from '../../../icon' -import { HeatLoadGrid } from '../HeatLoadGrid' +import { SummaryOutputSchema } from '../../../../../../types/types.ts' +import { Icon } from '../../../icon.tsx' +import { HeatLoadGrid } from '../HeatLoadGrid.tsx' import { COLOR_GREY_LIGHT, COLOR_ORANGE, COLOR_BLUE, -} from '../constants' +} from '../constants.ts' import { calculateAvgHeatLoad, calculateMaxHeatLoad, -} from '../utility/heat-load-calculations' -import { buildHeatLoadGraphData } from '../utility/build-heat-load-graph-data' -import { HeatLoadGraphToolTip } from './HeatLoadGraphToolTip' -import { CustomLegend } from './HeatLoadGraphLegend' -import { DESIGN_SET_POINT } from '../../../../../global_constants' +} from '../utility/heat-load-calculations.ts' +import { buildHeatLoadGraphData } from '../utility/build-heat-load-graph-data.ts' +import { HeatLoadGraphToolTip } from './HeatLoadGraphToolTip.tsx' +import { CustomLegend } from './HeatLoadGraphLegend.tsx' +import { DESIGN_SET_POINT } from '../../../../../global_constants.ts' const X_AXIS_BUFFER_PERCENTAGE_MAX = 1.3; // 30% buffer const Y_AXIS_ROUNDING_UNIT = 10000; // Rounding unit for minY and maxY diff --git a/heat-stack/app/components/ui/heat/CaseSummaryComponents/Graphs/HeatLoadGraphLegend.tsx b/heat-stack/app/components/ui/heat/CaseSummaryComponents/Graphs/HeatLoadGraphLegend.tsx index 6ff7ca95..d673cc95 100644 --- a/heat-stack/app/components/ui/heat/CaseSummaryComponents/Graphs/HeatLoadGraphLegend.tsx +++ b/heat-stack/app/components/ui/heat/CaseSummaryComponents/Graphs/HeatLoadGraphLegend.tsx @@ -1,7 +1,7 @@ import { COLOR_ORANGE, COLOR_BLUE, -} from '../constants' +} from '../constants.ts' export const CustomLegend = () => { const legendItems = [ diff --git a/heat-stack/app/components/ui/heat/CaseSummaryComponents/HeatLoadAnalysis.tsx b/heat-stack/app/components/ui/heat/CaseSummaryComponents/HeatLoadAnalysis.tsx index 059f7ad2..cc22cfe9 100644 --- a/heat-stack/app/components/ui/heat/CaseSummaryComponents/HeatLoadAnalysis.tsx +++ b/heat-stack/app/components/ui/heat/CaseSummaryComponents/HeatLoadAnalysis.tsx @@ -1,5 +1,4 @@ // import { AnalysisHeader } from './AnalysisHeader.tsx' -import React from 'react' import { HeatLoad } from './Graphs/HeatLoad.tsx' import { WholeHomeUAComparison } from './Graphs/WholeHomeUAComparison.tsx' diff --git a/heat-stack/app/components/ui/heat/CaseSummaryComponents/HeatLoadGrid.tsx b/heat-stack/app/components/ui/heat/CaseSummaryComponents/HeatLoadGrid.tsx index f56cde06..354e871a 100644 --- a/heat-stack/app/components/ui/heat/CaseSummaryComponents/HeatLoadGrid.tsx +++ b/heat-stack/app/components/ui/heat/CaseSummaryComponents/HeatLoadGrid.tsx @@ -1,5 +1,3 @@ -import React from 'react' - type HeatLoadGridProps = { setPoint: number averageHeatLoad: number @@ -22,7 +20,7 @@ export const HeatLoadGrid = ({ setPoint, averageHeatLoad, maxHeatLoad, -}: HeatLoadGridProps) => { +}: HeatLoadGridProps): JSX.Element => { return (
diff --git a/heat-stack/app/components/ui/heat/CaseSummaryComponents/utility/build-heat-load-graph-data.ts b/heat-stack/app/components/ui/heat/CaseSummaryComponents/utility/build-heat-load-graph-data.ts index dd09b2ff..db76d02a 100644 --- a/heat-stack/app/components/ui/heat/CaseSummaryComponents/utility/build-heat-load-graph-data.ts +++ b/heat-stack/app/components/ui/heat/CaseSummaryComponents/utility/build-heat-load-graph-data.ts @@ -1,9 +1,9 @@ -import { SummaryOutputSchema } from '../../../../../../types/types'; +import { SummaryOutputSchema } from '../../../../../../types/types.ts'; import { calculateAvgHeatLoad, calculateAvgHeatLoadEndPoint, calculateMaxHeatLoad, -} from './heat-load-calculations'; +} from './heat-load-calculations.ts'; type HeatLoadGraphPoint = { temperature: number diff --git a/heat-stack/app/components/ui/heat/CaseSummaryComponents/utility/heat-load-calculations.ts b/heat-stack/app/components/ui/heat/CaseSummaryComponents/utility/heat-load-calculations.ts index 0f5d7c31..edc95c0d 100644 --- a/heat-stack/app/components/ui/heat/CaseSummaryComponents/utility/heat-load-calculations.ts +++ b/heat-stack/app/components/ui/heat/CaseSummaryComponents/utility/heat-load-calculations.ts @@ -1,4 +1,4 @@ -import { SummaryOutputSchema } from '../../../../../../types/types' +import { SummaryOutputSchema } from '../../../../../../types/types.ts' // Utility file for helper functions related to calculating heat load // calculations are based on documentation found here: https://docs.google.com/document/d/16WlqY3ofq4xpalsfwRuYBWMbeUHfXRvbWU69xxVNCGM/edit?tab=t.0#heading=h.tl7o1hwvhavz 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 cd027b5c..6e5006fa 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..c9865051 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:'], 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..7ba54f83 100644 --- a/heat-stack/tsconfig.json +++ b/heat-stack/tsconfig.json @@ -1,30 +1,40 @@ { - "include": ["**/*.ts", "**/*.tsx"], - "extends": ["@epic-web/config/typescript"], + "extends": ["@epic-web/config/typescript"], // Uses a shared TypeScript configuration provided by the @epic-web package as the base. "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, - "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).q + "esModuleInterop": true, // Enables compatibility with CommonJS modules. + "noUncheckedIndexedAccess": true, // https://www.totaltypescript.com/tips/make-accessing-objects-safer-by-enabling-nouncheckedindexedaccess-in-tsconfig + "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, - } + }, + "include": [ + "**/*.ts", + "**/*.tsx" + ], + "exclude": [ + "node_modules", + "/build", + "/build/**/*", + "dist", + ".cache" + ] } 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';