Skip to content

Commit

Permalink
feat: fix biome linting
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewdoro committed May 2, 2024
1 parent 03b1972 commit 081ab3b
Show file tree
Hide file tree
Showing 57 changed files with 784 additions and 784 deletions.
2 changes: 0 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@ yarn.lock
*.tsbuildinfo
next-env.d.ts

# vscode
.vscode

# intellij
.idea
Expand Down
8 changes: 8 additions & 0 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"recommendations": [
"yoavbls.pretty-ts-errors",
"bradlc.vscode-tailwindcss",
"biomejs.biome"
]
}

29 changes: 29 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"editor.codeActionsOnSave": {
"source.organizeImports.biome": "explicit",
"source.fixAll.biome": "explicit",
// "quickfix.biome": "explicit"
},
"editor.defaultFormatter": "biomejs.biome",
"editor.formatOnSave": true,
"tailwindCSS.experimental.classRegex": [
["cva\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]"],
["cx\\(([^)]*)\\)", "(?:'|\"|`)([^']*)(?:'|\"|`)"]
],
"typescript.enablePromptUseWorkspaceTsdk": true,
"typescript.tsdk": "node_modules/typescript/lib",

"typescript.preferences.autoImportFileExcludePatterns": [
"next/router.d.ts",
"next/dist/client/router.d.ts"
],
"[typescriptreact]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[typescript]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[json]": {
"editor.defaultFormatter": "vscode.json-language-features"
}
}
108 changes: 51 additions & 57 deletions apps/web/app/api/generate/route.ts
Original file line number Diff line number Diff line change
@@ -1,135 +1,129 @@
import OpenAI from 'openai';
import { OpenAIStream, StreamingTextResponse } from 'ai';
import { kv } from '@vercel/kv';
import { Ratelimit } from '@upstash/ratelimit';
import { match } from 'ts-pattern';
import type { ChatCompletionMessageParam } from 'openai/resources/index.mjs';
import { Ratelimit } from "@upstash/ratelimit";
import { kv } from "@vercel/kv";
import { OpenAIStream, StreamingTextResponse } from "ai";
import OpenAI from "openai";
import type { ChatCompletionMessageParam } from "openai/resources/index.mjs";
import { match } from "ts-pattern";

// Create an OpenAI API client (that's edge friendly!)
// Using LLamma's OpenAI client:

// IMPORTANT! Set the runtime to edge: https://vercel.com/docs/functions/edge-functions/edge-runtime
export const runtime = 'edge';

const llama = new OpenAI({
apiKey: 'ollama',
baseURL: 'http://localhost:11434/v1',
});
export const runtime = "edge";

export async function POST(req: Request): Promise<Response> {
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
baseURL: process.env.OPENAI_BASE_URL || 'https://api.openai.com/v1',
baseURL: process.env.OPENAI_BASE_URL || "https://api.openai.com/v1",
});
// Check if the OPENAI_API_KEY is set, if not return 400
if (!process.env.OPENAI_API_KEY || process.env.OPENAI_API_KEY === '') {
return new Response('Missing OPENAI_API_KEY - make sure to add it to your .env file.', {
if (!process.env.OPENAI_API_KEY || process.env.OPENAI_API_KEY === "") {
return new Response("Missing OPENAI_API_KEY - make sure to add it to your .env file.", {
status: 400,
});
}
if (process.env.KV_REST_API_URL && process.env.KV_REST_API_TOKEN) {
const ip = req.headers.get('x-forwarded-for');
const ip = req.headers.get("x-forwarded-for");
const ratelimit = new Ratelimit({
redis: kv,
limiter: Ratelimit.slidingWindow(50, '1 d'),
limiter: Ratelimit.slidingWindow(50, "1 d"),
});

const { success, limit, reset, remaining } = await ratelimit.limit(`novel_ratelimit_${ip}`);

if (!success) {
return new Response('You have reached your request limit for the day.', {
return new Response("You have reached your request limit for the day.", {
status: 429,
headers: {
'X-RateLimit-Limit': limit.toString(),
'X-RateLimit-Remaining': remaining.toString(),
'X-RateLimit-Reset': reset.toString(),
"X-RateLimit-Limit": limit.toString(),
"X-RateLimit-Remaining": remaining.toString(),
"X-RateLimit-Reset": reset.toString(),
},
});
}
}

const { prompt, option, command } = await req.json();
const messages = match(option)
.with('continue', () => [
.with("continue", () => [
{
role: 'system',
role: "system",
content:
'You are an AI writing assistant that continues existing text based on context from prior text. ' +
'Give more weight/priority to the later characters than the beginning ones. ' +
'Limit your response to no more than 200 characters, but make sure to construct complete sentences.' +
'Use Markdown formatting when appropriate.',
"You are an AI writing assistant that continues existing text based on context from prior text. " +
"Give more weight/priority to the later characters than the beginning ones. " +
"Limit your response to no more than 200 characters, but make sure to construct complete sentences." +
"Use Markdown formatting when appropriate.",
},
{
role: 'user',
role: "user",
content: prompt,
},
])
.with('improve', () => [
.with("improve", () => [
{
role: 'system',
role: "system",
content:
'You are an AI writing assistant that improves existing text. ' +
'Limit your response to no more than 200 characters, but make sure to construct complete sentences.' +
'Use Markdown formatting when appropriate.',
"You are an AI writing assistant that improves existing text. " +
"Limit your response to no more than 200 characters, but make sure to construct complete sentences." +
"Use Markdown formatting when appropriate.",
},
{
role: 'user',
role: "user",
content: `The existing text is: ${prompt}`,
},
])
.with('shorter', () => [
.with("shorter", () => [
{
role: 'system',
role: "system",
content:
'You are an AI writing assistant that shortens existing text. ' + 'Use Markdown formatting when appropriate.',
"You are an AI writing assistant that shortens existing text. " + "Use Markdown formatting when appropriate.",
},
{
role: 'user',
role: "user",
content: `The existing text is: ${prompt}`,
},
])
.with('longer', () => [
.with("longer", () => [
{
role: 'system',
role: "system",
content:
'You are an AI writing assistant that lengthens existing text. ' +
'Use Markdown formatting when appropriate.',
"You are an AI writing assistant that lengthens existing text. " +
"Use Markdown formatting when appropriate.",
},
{
role: 'user',
role: "user",
content: `The existing text is: ${prompt}`,
},
])
.with('fix', () => [
.with("fix", () => [
{
role: 'system',
role: "system",
content:
'You are an AI writing assistant that fixes grammar and spelling errors in existing text. ' +
'Limit your response to no more than 200 characters, but make sure to construct complete sentences.' +
'Use Markdown formatting when appropriate.',
"You are an AI writing assistant that fixes grammar and spelling errors in existing text. " +
"Limit your response to no more than 200 characters, but make sure to construct complete sentences." +
"Use Markdown formatting when appropriate.",
},
{
role: 'user',
role: "user",
content: `The existing text is: ${prompt}`,
},
])
.with('zap', () => [
.with("zap", () => [
{
role: 'system',
role: "system",
content:
'You area an AI writing assistant that generates text based on a prompt. ' +
'You take an input from the user and a command for manipulating the text' +
'Use Markdown formatting when appropriate.',
"You area an AI writing assistant that generates text based on a prompt. " +
"You take an input from the user and a command for manipulating the text" +
"Use Markdown formatting when appropriate.",
},
{
role: 'user',
role: "user",
content: `For this text: ${prompt}. You have to respect the command: ${command}`,
},
])
.run() as ChatCompletionMessageParam[];

const response = await openai.chat.completions.create({
model: 'gpt-3.5-turbo',
model: "gpt-3.5-turbo",
stream: true,
messages,
temperature: 0.7,
Expand Down
16 changes: 8 additions & 8 deletions apps/web/app/api/upload/route.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { put } from '@vercel/blob';
import { NextResponse } from 'next/server';
import { put } from "@vercel/blob";
import { NextResponse } from "next/server";

export const runtime = 'edge';
export const runtime = "edge";

export async function POST(req: Request) {
if (!process.env.BLOB_READ_WRITE_TOKEN) {
Expand All @@ -10,16 +10,16 @@ export async function POST(req: Request) {
});
}

const file = req.body || '';
const filename = req.headers.get('x-vercel-filename') || 'file.txt';
const contentType = req.headers.get('content-type') || 'text/plain';
const fileType = `.${contentType.split('/')[1]}`;
const file = req.body || "";
const filename = req.headers.get("x-vercel-filename") || "file.txt";
const contentType = req.headers.get("content-type") || "text/plain";
const fileType = `.${contentType.split("/")[1]}`;

// construct final filename based on content-type if not provided
const finalName = filename.includes(fileType) ? filename : `${filename}${fileType}`;
const blob = await put(finalName, file, {
contentType,
access: 'public',
access: "public",
});

return NextResponse.json(blob);
Expand Down
22 changes: 11 additions & 11 deletions apps/web/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import '@/styles/globals.css';
import '@/styles/prosemirror.css';
import "@/styles/globals.css";
import "@/styles/prosemirror.css";

import type { Metadata, Viewport } from 'next';
import type { ReactNode } from 'react';
import Providers from './providers';
import type { Metadata, Viewport } from "next";
import type { ReactNode } from "react";
import Providers from "./providers";

const title = 'Novel - Notion-style WYSIWYG editor with AI-powered autocompletions';
const title = "Novel - Notion-style WYSIWYG editor with AI-powered autocompletions";
const description =
'Novel is a Notion-style WYSIWYG editor with AI-powered autocompletions. Built with Tiptap, OpenAI, and Vercel AI SDK.';
"Novel is a Notion-style WYSIWYG editor with AI-powered autocompletions. Built with Tiptap, OpenAI, and Vercel AI SDK.";

export const metadata: Metadata = {
title,
Expand All @@ -19,14 +19,14 @@ export const metadata: Metadata = {
twitter: {
title,
description,
card: 'summary_large_image',
creator: '@steventey',
card: "summary_large_image",
creator: "@steventey",
},
metadataBase: new URL('https://novel.sh'),
metadataBase: new URL("https://novel.sh"),
};

export const viewport: Viewport = {
themeColor: '#ffffff',
themeColor: "#ffffff",
};

export default function RootLayout({ children }: { children: ReactNode }) {
Expand Down
17 changes: 8 additions & 9 deletions apps/web/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
import { Github } from '@/components/tailwind/ui/icons';
import { Button } from '@/components/tailwind/ui/button';
import Menu from '@/components/tailwind/ui/menu';
import Link from 'next/link';
import TailwindAdvancedEditor from '@/components/tailwind/advanced-editor';
import { Dialog, DialogContent, DialogTrigger } from '@/components/tailwind/ui/dialog';
import { ScrollArea } from '@/components/tailwind/ui/scroll-area';
import { BookOpen } from 'lucide-react';
import TailwindAdvancedEditor from "@/components/tailwind/advanced-editor";
import { Button } from "@/components/tailwind/ui/button";
import { Dialog, DialogContent, DialogTrigger } from "@/components/tailwind/ui/dialog";
import Menu from "@/components/tailwind/ui/menu";
import { ScrollArea } from "@/components/tailwind/ui/scroll-area";
import { BookOpen, GithubIcon } from "lucide-react";
import Link from "next/link";

export default function Page() {
return (
<div className="flex min-h-screen flex-col items-center gap-4 py-4 sm:px-5">
<div className="flex w-full max-w-screen-lg items-center gap-2 px-4 sm:mb-[calc(20vh)]">
<Button size="icon" variant="outline">
<a href="https://github.com/steven-tey/novel" target="_blank" rel="noreferrer">
<Github />
<GithubIcon />
</a>
</Button>
<Dialog>
Expand Down
18 changes: 9 additions & 9 deletions apps/web/app/providers.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
'use client';
"use client";

import { type Dispatch, type ReactNode, type SetStateAction, createContext } from 'react';
import { ThemeProvider, useTheme } from 'next-themes';
import { Toaster } from 'sonner';
import { Analytics } from '@vercel/analytics/react';
import useLocalStorage from '@/hooks/use-local-storage';
import { type Dispatch, type ReactNode, type SetStateAction, createContext } from "react";
import { ThemeProvider, useTheme } from "next-themes";
import { Toaster } from "sonner";
import { Analytics } from "@vercel/analytics/react";
import useLocalStorage from "@/hooks/use-local-storage";

export const AppContext = createContext<{
font: string;
setFont: Dispatch<SetStateAction<string>>;
}>({
font: 'Default',
font: "Default",
setFont: () => {},
});

const ToasterProvider = () => {
const { theme } = useTheme() as {
theme: 'light' | 'dark' | 'system';
theme: "light" | "dark" | "system";
};
return <Toaster theme={theme} />;
};

export default function Providers({ children }: { children: ReactNode }) {
const [font, setFont] = useLocalStorage<string>('novel__font', 'Default');
const [font, setFont] = useLocalStorage<string>("novel__font", "Default");

return (
<ThemeProvider attribute="class" enableSystem disableTransitionOnChange defaultTheme="system">
Expand Down
Loading

0 comments on commit 081ab3b

Please sign in to comment.