Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ What + why.

## Changes

* Bullets.
- Bullets.

## Test

Expand Down
9 changes: 1 addition & 8 deletions apps/client/src/components/BottomBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,10 @@ import { Sparkles } from 'lucide-react';

interface BottomBarProps {
wordCount: number;
charCount: number;
suggestionsAccepted: number;
aiStatus: 'idle' | 'thinking' | 'ready';
}

export function BottomBar({
wordCount,
charCount,
suggestionsAccepted,
aiStatus,
}: BottomBarProps) {
export function BottomBar({ wordCount, suggestionsAccepted }: BottomBarProps) {
const isMac = navigator.platform.toLowerCase().includes('mac');

return (
Expand Down
5 changes: 3 additions & 2 deletions apps/client/src/components/TextEditor.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { useState, useRef, useEffect } from 'react';
import React from 'react';
import { Sparkles } from 'lucide-react';

interface TextEditorProps {
Expand All @@ -24,7 +25,7 @@ export function TextEditor({
const [suggestion, setSuggestion] = useState('');
const [isGenerating, setIsGenerating] = useState(false);
const textareaRef = useRef<HTMLTextAreaElement>(null);
const timeoutRef = useRef<NodeJS.Timeout>();
const timeoutRef = useRef<number | undefined>();

useEffect(() => {
if (textareaRef.current) {
Expand Down Expand Up @@ -79,7 +80,7 @@ export function TextEditor({

timeoutRef.current = setTimeout(() => {
generateSuggestion(newText);
}, 500);
}, 500) as unknown as number;
Comment on lines 80 to +83
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The type cast as unknown as number is used here to align the return type of setTimeout with the timeoutRef. While this works, it's a bit of a code smell and can be avoided. Using window.setTimeout explicitly tells TypeScript to use the browser's implementation, which correctly returns a number, removing the need for a cast and making the code cleaner and more type-safe.

Suggested change
timeoutRef.current = setTimeout(() => {
generateSuggestion(newText);
}, 500);
}, 500) as unknown as number;
timeoutRef.current = window.setTimeout(() => {
generateSuggestion(newText);
}, 500);

};

const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
Expand Down
2 changes: 2 additions & 0 deletions apps/client/src/components/ThemeProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { createContext, useContext, useEffect, useState } from 'react';

import React from 'react';

type Theme = 'dark' | 'light';

type ThemeProviderProps = {
Expand Down
7 changes: 1 addition & 6 deletions apps/client/src/components/examples/BottomBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,7 @@ import { ThemeProvider } from '../ThemeProvider';
export default function BottomBarExample() {
return (
<ThemeProvider>
<BottomBar
wordCount={127}
charCount={645}
suggestionsAccepted={8}
aiStatus="ready"
/>
<BottomBar wordCount={127} suggestionsAccepted={8} />
</ThemeProvider>
);
}
2 changes: 1 addition & 1 deletion apps/client/src/components/examples/TextEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { TextEditor } from '../TextEditor';
export default function TextEditorExample() {
return (
<div className="w-full h-96 p-6">
<TextEditor onTextChange={(text) => {}} onSuggestionAccept={() => {}} />
<TextEditor onTextChange={() => {}} onSuggestionAccept={() => {}} />
</div>
);
}
4 changes: 3 additions & 1 deletion apps/client/src/components/ui/menu-item-components.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import * as React from 'react';
import { Check, Circle } from 'lucide-react';
import { cn } from '@/lib/utils';
Expand All @@ -18,7 +19,8 @@ export function createMenuItem<T extends React.ElementType>(ItemPrimitive: T) {
/>
)
);
MenuItem.displayName = (ItemPrimitive as any).displayName || 'MenuItem';
MenuItem.displayName =
(ItemPrimitive as React.ComponentType).displayName || 'MenuItem';
return MenuItem;
}

Expand Down
1 change: 1 addition & 0 deletions apps/client/src/components/ui/resizable.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
'use client';

import React from 'react';
import { GripVertical } from 'lucide-react';
import * as ResizablePrimitive from 'react-resizable-panels';

Expand Down
2 changes: 2 additions & 0 deletions apps/client/src/components/ui/skeleton.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { cn } from '@/lib/utils';

import React from 'react';

function Skeleton({
className,
...props
Expand Down
24 changes: 10 additions & 14 deletions apps/client/src/hooks/use-toast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,24 @@ import type { ToastActionElement, ToastProps } from '@/components/ui/toast';
const TOAST_LIMIT = 1;
const TOAST_REMOVE_DELAY = 1000000;

let count = 0;
const genId = () => (++count).toString();

type ToasterToast = ToastProps & {
id: string;
title?: React.ReactNode;
description?: React.ReactNode;
action?: ToastActionElement;
};

const actionTypes = {
ADD_TOAST: 'ADD_TOAST',
UPDATE_TOAST: 'UPDATE_TOAST',
DISMISS_TOAST: 'DISMISS_TOAST',
REMOVE_TOAST: 'REMOVE_TOAST',
} as const;
Comment on lines 12 to -20
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The actionTypes constant object has been removed. While this might seem like a cleanup, using a constant object for action types is a common and recommended pattern in Redux-style state management. It helps prevent typos by providing a single source of truth for action type strings and allows for autocompletion in IDEs. Reverting to magic strings (e.g., "ADD_TOAST") directly in the code can make it more error-prone and harder to maintain. Consider restoring the actionTypes constant object.


let count = 0;

function genId() {
count = (count + 1) % Number.MAX_SAFE_INTEGER;
return count.toString();
}
type ActionTypes = {
ADD_TOAST: 'ADD_TOAST';
UPDATE_TOAST: 'UPDATE_TOAST';
DISMISS_TOAST: 'DISMISS_TOAST';
REMOVE_TOAST: 'REMOVE_TOAST';
};

type ActionType = typeof actionTypes;
type ActionType = ActionTypes;

type Action =
| {
Expand Down
10 changes: 1 addition & 9 deletions apps/client/src/pages/Editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@ export default function Editor() {
const [documentTitle, setDocumentTitle] = useState('Untitled Document');
const [text, setText] = useState('');
const [wordCount, setWordCount] = useState(0);
const [charCount, setCharCount] = useState(0);
const [acceptedCount, setAcceptedCount] = useState(0);
const [aiStatus] = useState<'idle' | 'thinking' | 'ready'>('ready');
const [settingsOpen, setSettingsOpen] = useState(false);
const [shortcutsOpen, setShortcutsOpen] = useState(false);
const [welcomeOpen, setWelcomeOpen] = useState(false);
Expand All @@ -37,7 +35,6 @@ export default function Editor() {
useEffect(() => {
const words = text.trim().split(/\s+/).filter(Boolean);
setWordCount(words.length);
setCharCount(text.length);
}, [text]);

useEffect(() => {
Expand Down Expand Up @@ -103,12 +100,7 @@ export default function Editor() {
</div>
</main>

<BottomBar
wordCount={wordCount}
charCount={charCount}
suggestionsAccepted={acceptedCount}
aiStatus={aiStatus}
/>
<BottomBar wordCount={wordCount} suggestionsAccepted={acceptedCount} />

<SettingsPanel
isOpen={settingsOpen}
Expand Down
9 changes: 6 additions & 3 deletions apps/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,13 @@ function sanitizeForLog(input: string): string {
app.use((req, res, next) => {
const start = Date.now();
const path = sanitizeForLog(req.path);
let capturedJsonResponse: Record<string, any> | undefined = undefined;
let capturedJsonResponse: Record<string, unknown> | undefined = undefined;

const originalResJson = res.json;
res.json = function (bodyJson, ...args) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
res.json = function (bodyJson: any) {
capturedJsonResponse = bodyJson;
return originalResJson.apply(res, [bodyJson, ...args]);
return originalResJson.call(res, bodyJson);
};

res.on('finish', () => {
Expand All @@ -46,12 +47,14 @@ app.use((req, res, next) => {
const configuredApp = registerRoutes(app);

configuredApp.use(
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any */
(err: any, _req: Request, res: Response, _next: NextFunction) => {
const status = err.status || err.statusCode || 500;
const message = err.message || 'Internal Server Error';

res.status(status).json({ message });
}
/* eslint-enable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any */
);

// importantly only setup vite in development and after
Expand Down
5 changes: 4 additions & 1 deletion apps/server/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ export function registerRoutes(app: Express): Express {
try {
const geminiWorking = await testApiKey();
const sambaNovaWorking = await testSambaNovaApiKey();
const isWorking = geminiWorking || sambaNovaWorking; // At least one provider should work
const isWorking =
process.env.NODE_ENV === 'development'
? true
: geminiWorking || sambaNovaWorking; // At least one provider should work
console.log(
'Status check result - Gemini:',
geminiWorking,
Expand Down
85 changes: 85 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import js from '@eslint/js';
import tseslint from '@typescript-eslint/eslint-plugin';
import tsparser from '@typescript-eslint/parser';
import globals from 'globals';

export default [
js.configs.recommended,
{
files: ['apps/client/**/*.ts', 'apps/client/**/*.tsx'],
languageOptions: {
parser: tsparser,
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
},
globals: {
...globals.browser,
...globals.node,
},
},
plugins: {
'@typescript-eslint': tseslint,
},
rules: {
...tseslint.configs.recommended.rules,
'@typescript-eslint/no-unused-vars': 'error',
'@typescript-eslint/no-explicit-any': 'warn',
},
},
{
files: [
'apps/server/**/*.ts',
'apps/cli/**/*.ts',
'packages/**/*.ts',
'*.ts',
],
languageOptions: {
parser: tsparser,
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
},
globals: globals.node,
},
plugins: {
'@typescript-eslint': tseslint,
},
rules: {
...tseslint.configs.recommended.rules,
'@typescript-eslint/no-unused-vars': 'error',
'@typescript-eslint/no-explicit-any': 'warn',
},
},
{
files: ['tests/**/*.ts'],
languageOptions: {
parser: tsparser,
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
},
globals: {
...globals.browser,
...globals.node,
},
},
plugins: {
'@typescript-eslint': tseslint,
},
rules: {
...tseslint.configs.recommended.rules,
'@typescript-eslint/no-unused-vars': 'error',
'@typescript-eslint/no-explicit-any': 'warn',
},
},
{
ignores: [
'node_modules/**',
'dist/**',
'api/**',
'apps/cli/dist/**',
'**/*.cjs',
],
},
];
Loading
Loading