tighter types and linting

This commit is contained in:
Kyle Corbitt
2023-06-26 23:40:05 -07:00
parent 4742d9bd02
commit bca35c9eb2
20 changed files with 64 additions and 29 deletions

View File

@@ -20,7 +20,7 @@ const config = {
parserOptions: { parserOptions: {
project: path.join(__dirname, "tsconfig.json"), project: path.join(__dirname, "tsconfig.json"),
}, },
plugins: ["@typescript-eslint"], plugins: ["@typescript-eslint", "unused-imports"],
extends: ["next/core-web-vitals", "plugin:@typescript-eslint/recommended"], extends: ["next/core-web-vitals", "plugin:@typescript-eslint/recommended"],
rules: { rules: {
"@typescript-eslint/consistent-type-imports": [ "@typescript-eslint/consistent-type-imports": [
@@ -31,6 +31,12 @@ const config = {
}, },
], ],
"@typescript-eslint/no-unused-vars": ["warn", { argsIgnorePattern: "^_" }], "@typescript-eslint/no-unused-vars": ["warn", { argsIgnorePattern: "^_" }],
"unused-imports/no-unused-imports": "error",
"unused-imports/no-unused-vars": [
"warn",
{ vars: "all", varsIgnorePattern: "^_", args: "after-used", argsIgnorePattern: "^_" },
],
}, },
}; };

6
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"eslint.format.enable": true,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
}
}

View File

@@ -53,6 +53,7 @@
"@typescript-eslint/parser": "^5.59.6", "@typescript-eslint/parser": "^5.59.6",
"eslint": "^8.40.0", "eslint": "^8.40.0",
"eslint-config-next": "^13.4.2", "eslint-config-next": "^13.4.2",
"eslint-plugin-unused-imports": "^2.0.0",
"prisma": "^4.14.0", "prisma": "^4.14.0",
"typescript": "^5.0.4", "typescript": "^5.0.4",
"yaml": "^2.3.1" "yaml": "^2.3.1"

23
pnpm-lock.yaml generated
View File

@@ -124,6 +124,9 @@ devDependencies:
eslint-config-next: eslint-config-next:
specifier: ^13.4.2 specifier: ^13.4.2
version: 13.4.2(eslint@8.40.0)(typescript@5.0.4) version: 13.4.2(eslint@8.40.0)(typescript@5.0.4)
eslint-plugin-unused-imports:
specifier: ^2.0.0
version: 2.0.0(@typescript-eslint/eslint-plugin@5.59.6)(eslint@8.40.0)
prisma: prisma:
specifier: ^4.14.0 specifier: ^4.14.0
version: 4.14.0 version: 4.14.0
@@ -2968,6 +2971,26 @@ packages:
string.prototype.matchall: 4.0.8 string.prototype.matchall: 4.0.8
dev: true dev: true
/eslint-plugin-unused-imports@2.0.0(@typescript-eslint/eslint-plugin@5.59.6)(eslint@8.40.0):
resolution: {integrity: sha512-3APeS/tQlTrFa167ThtP0Zm0vctjr4M44HMpeg1P4bK6wItarumq0Ma82xorMKdFsWpphQBlRPzw/pxiVELX1A==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
'@typescript-eslint/eslint-plugin': ^5.0.0
eslint: ^8.0.0
peerDependenciesMeta:
'@typescript-eslint/eslint-plugin':
optional: true
dependencies:
'@typescript-eslint/eslint-plugin': 5.59.6(@typescript-eslint/parser@5.59.6)(eslint@8.40.0)(typescript@5.0.4)
eslint: 8.40.0
eslint-rule-composer: 0.3.0
dev: true
/eslint-rule-composer@0.3.0:
resolution: {integrity: sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg==}
engines: {node: '>=4.0.0'}
dev: true
/eslint-scope@5.1.1: /eslint-scope@5.1.1:
resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==}
engines: {node: '>=8.0.0'} engines: {node: '>=8.0.0'}

View File

@@ -5,7 +5,7 @@ import fs from "fs";
import path from "path"; import path from "path";
import { openapiSchemaToJsonSchema } from "@openapi-contrib/openapi-schema-to-json-schema"; import { openapiSchemaToJsonSchema } from "@openapi-contrib/openapi-schema-to-json-schema";
import assert from "assert"; import assert from "assert";
import { AcceptibleInputSchema } from "@openapi-contrib/openapi-schema-to-json-schema/dist/mjs/openapi-schema-types"; import { type AcceptibleInputSchema } from "@openapi-contrib/openapi-schema-to-json-schema/dist/mjs/openapi-schema-types";
const OPENAPI_URL = const OPENAPI_URL =
"https://raw.githubusercontent.com/openai/openai-openapi/0c432eb66fd0c758fd8b9bd69db41c1096e5f4db/openapi.yaml"; "https://raw.githubusercontent.com/openai/openai-openapi/0c432eb66fd0c758fd8b9bd69db41c1096e5f4db/openapi.yaml";

View File

@@ -1,4 +1,4 @@
import { Button, Tooltip } from "@chakra-ui/react"; import { Button } from "@chakra-ui/react";
import { BsPlus } from "react-icons/bs"; import { BsPlus } from "react-icons/bs";
import { api } from "~/utils/api"; import { api } from "~/utils/api";
import { useExperiment, useHandledAsyncCallback } from "~/utils/hooks"; import { useExperiment, useHandledAsyncCallback } from "~/utils/hooks";

View File

@@ -1,5 +1,5 @@
import { api } from "~/utils/api"; import { api } from "~/utils/api";
import { PromptVariant, Scenario } from "./types"; import { type PromptVariant, type Scenario } from "./types";
import { Center, Spinner, Text } from "@chakra-ui/react"; import { Center, Spinner, Text } from "@chakra-ui/react";
import { useExperiment } from "~/utils/hooks"; import { useExperiment } from "~/utils/hooks";
import { cellPadding } from "../constants"; import { cellPadding } from "../constants";

View File

@@ -1,4 +1,4 @@
import { useRef, useState, type DragEvent } from "react"; import { useState, type DragEvent } from "react";
import { type PromptVariant } from "./types"; import { type PromptVariant } from "./types";
import { api } from "~/utils/api"; import { api } from "~/utils/api";
import { useHandledAsyncCallback } from "~/utils/hooks"; import { useHandledAsyncCallback } from "~/utils/hooks";

View File

@@ -1,4 +1,4 @@
import { RouterOutputs } from "~/utils/api"; import { type RouterOutputs } from "~/utils/api";
export type PromptVariant = NonNullable<RouterOutputs["promptVariants"]["list"]>[0]; export type PromptVariant = NonNullable<RouterOutputs["promptVariants"]["list"]>[0];

View File

@@ -1,15 +1,12 @@
import { import {
Box, Box,
Flex, Flex,
Stack,
Button,
Heading, Heading,
VStack, VStack,
Icon, Icon,
HStack, HStack,
BoxProps, type BoxProps,
forwardRef, forwardRef,
Divider,
Image, Image,
} from "@chakra-ui/react"; } from "@chakra-ui/react";
import Head from "next/head"; import Head from "next/head";

View File

@@ -10,19 +10,18 @@ export const env = createEnv({
DATABASE_URL: z.string().url(), DATABASE_URL: z.string().url(),
NODE_ENV: z.enum(["development", "test", "production"]), NODE_ENV: z.enum(["development", "test", "production"]),
NEXTAUTH_SECRET: NEXTAUTH_SECRET:
process.env.NODE_ENV === "production" process.env.NODE_ENV === "production" ? z.string().min(1) : z.string().min(1).optional(),
? z.string().min(1)
: z.string().min(1).optional(),
NEXTAUTH_URL: z.preprocess( NEXTAUTH_URL: z.preprocess(
// This makes Vercel deployments not fail if you don't set NEXTAUTH_URL // This makes Vercel deployments not fail if you don't set NEXTAUTH_URL
// Since NextAuth.js automatically uses the VERCEL_URL if present. // Since NextAuth.js automatically uses the VERCEL_URL if present.
(str) => process.env.VERCEL_URL ?? str, (str) => process.env.VERCEL_URL ?? str,
// VERCEL_URL doesn't include `https` so it cant be validated as a URL // VERCEL_URL doesn't include `https` so it cant be validated as a URL
process.env.VERCEL ? z.string().min(1) : z.string().url(), process.env.VERCEL ? z.string().min(1) : z.string().url()
), ),
// Add `.min(1) on ID and SECRET if you want to make sure they're not empty // Add `.min(1) on ID and SECRET if you want to make sure they're not empty
DISCORD_CLIENT_ID: z.string(), DISCORD_CLIENT_ID: z.string(),
DISCORD_CLIENT_SECRET: z.string(), DISCORD_CLIENT_SECRET: z.string(),
OPENAI_API_KEY: z.string().min(1),
}, },
/** /**
@@ -45,6 +44,7 @@ export const env = createEnv({
NEXTAUTH_URL: process.env.NEXTAUTH_URL, NEXTAUTH_URL: process.env.NEXTAUTH_URL,
DISCORD_CLIENT_ID: process.env.DISCORD_CLIENT_ID, DISCORD_CLIENT_ID: process.env.DISCORD_CLIENT_ID,
DISCORD_CLIENT_SECRET: process.env.DISCORD_CLIENT_SECRET, DISCORD_CLIENT_SECRET: process.env.DISCORD_CLIENT_SECRET,
OPENAI_API_KEY: process.env.OPENAI_API_KEY,
}, },
/** /**
* Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation. * Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation.

View File

@@ -9,10 +9,9 @@ import {
HStack, HStack,
Icon, Icon,
Input, Input,
Tooltip,
} from "@chakra-ui/react"; } from "@chakra-ui/react";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { useState, useRef, useEffect } from "react"; import { useState, useEffect } from "react";
import { BsTrash } from "react-icons/bs"; import { BsTrash } from "react-icons/bs";
import { RiFlaskLine } from "react-icons/ri"; import { RiFlaskLine } from "react-icons/ri";
import OutputsTable from "~/components/OutputsTable"; import OutputsTable from "~/components/OutputsTable";

View File

@@ -1,6 +1,6 @@
import { Text, Box, Button, HStack, Heading, Icon, Input, Stack, Code } from "@chakra-ui/react"; import { Text, Button, HStack, Heading, Icon, Input, Stack, Code } from "@chakra-ui/react";
import { useState } from "react"; import { useState } from "react";
import { BsCheck, BsChevronDown, BsChevronUp, BsX } from "react-icons/bs"; import { BsCheck, BsChevronDown, BsX } from "react-icons/bs";
import { cellPadding } from "~/components/constants"; import { cellPadding } from "~/components/constants";
import { api } from "~/utils/api"; import { api } from "~/utils/api";
import { useExperiment, useHandledAsyncCallback } from "~/utils/hooks"; import { useExperiment, useHandledAsyncCallback } from "~/utils/hooks";
@@ -85,7 +85,7 @@ export default function ScenarioHeader() {
</HStack> </HStack>
<HStack spacing={2} py={4} wrap="wrap"> <HStack spacing={2} py={4} wrap="wrap">
{vars.map((variable, i) => ( {vars.map((variable) => (
<HStack <HStack
key={variable.id} key={variable.id}
spacing={0} spacing={0}

View File

@@ -1,5 +1,5 @@
import { z } from "zod"; import { z } from "zod";
import { createTRPCRouter, publicProcedure, protectedProcedure } from "~/server/api/trpc"; import { createTRPCRouter, publicProcedure } from "~/server/api/trpc";
import { prisma } from "~/server/db"; import { prisma } from "~/server/db";
export const experimentsRouter = createTRPCRouter({ export const experimentsRouter = createTRPCRouter({

View File

@@ -1,11 +1,14 @@
import { z } from "zod"; import { z } from "zod";
import { createTRPCRouter, publicProcedure, protectedProcedure } from "~/server/api/trpc"; import { createTRPCRouter, publicProcedure } from "~/server/api/trpc";
import { prisma } from "~/server/db"; import { prisma } from "~/server/db";
import fillTemplate, { VariableMap } from "~/server/utils/fillTemplate"; import fillTemplate, { type VariableMap } from "~/server/utils/fillTemplate";
import { JSONSerializable } from "~/server/types"; import { type JSONSerializable } from "~/server/types";
import { getChatCompletion } from "~/server/utils/openai"; import { getChatCompletion } from "~/server/utils/openai";
import crypto from "crypto"; import crypto from "crypto";
import type { Prisma } from "@prisma/client"; import type { Prisma } from "@prisma/client";
import { env } from "~/env.mjs";
env;
export const modelOutputsRouter = createTRPCRouter({ export const modelOutputsRouter = createTRPCRouter({
get: publicProcedure get: publicProcedure
@@ -56,7 +59,7 @@ export const modelOutputsRouter = createTRPCRouter({
if (existingResponse) { if (existingResponse) {
modelResponse = existingResponse.output as JSONSerializable; modelResponse = existingResponse.output as JSONSerializable;
} else { } else {
modelResponse = await getChatCompletion(filledTemplate, process.env.OPENAI_API_KEY!); modelResponse = await getChatCompletion(filledTemplate, env.OPENAI_API_KEY);
} }
const modelOutput = await prisma.modelOutput.create({ const modelOutput = await prisma.modelOutput.create({

View File

@@ -1,7 +1,7 @@
import { z } from "zod"; import { z } from "zod";
import { createTRPCRouter, publicProcedure } from "~/server/api/trpc"; import { createTRPCRouter, publicProcedure } from "~/server/api/trpc";
import { prisma } from "~/server/db"; import { prisma } from "~/server/db";
import { OpenAIChatConfig } from "~/server/types"; import { type OpenAIChatConfig } from "~/server/types";
export const promptVariantsRouter = createTRPCRouter({ export const promptVariantsRouter = createTRPCRouter({
list: publicProcedure.input(z.object({ experimentId: z.string() })).query(async ({ input }) => { list: publicProcedure.input(z.object({ experimentId: z.string() })).query(async ({ input }) => {

View File

@@ -1,5 +1,5 @@
import { z } from "zod"; import { z } from "zod";
import { createTRPCRouter, publicProcedure, protectedProcedure } from "~/server/api/trpc"; import { createTRPCRouter, publicProcedure } from "~/server/api/trpc";
import { prisma } from "~/server/db"; import { prisma } from "~/server/db";
export const scenariosRouter = createTRPCRouter({ export const scenariosRouter = createTRPCRouter({

View File

@@ -1,5 +1,5 @@
import { z } from "zod"; import { z } from "zod";
import { createTRPCRouter, publicProcedure, protectedProcedure } from "~/server/api/trpc"; import { createTRPCRouter, publicProcedure } from "~/server/api/trpc";
import { prisma } from "~/server/db"; import { prisma } from "~/server/db";
export const templateVarsRouter = createTRPCRouter({ export const templateVarsRouter = createTRPCRouter({

View File

@@ -1,4 +1,4 @@
import { JSONSerializable } from "../types"; import { type JSONSerializable } from "../types";
export type VariableMap = Record<string, string>; export type VariableMap = Record<string, string>;

View File

@@ -1,4 +1,4 @@
import { JSONSerializable } from "../types"; import { type JSONSerializable } from "../types";
export async function getChatCompletion(payload: JSONSerializable, apiKey: string) { export async function getChatCompletion(payload: JSONSerializable, apiKey: string) {
const response = await fetch("https://api.openai.com/v1/chat/completions", { const response = await fetch("https://api.openai.com/v1/chat/completions", {