Skip to content

Commit ee0fa82

Browse files
committed
prettier
1 parent 408abdf commit ee0fa82

19 files changed

Lines changed: 115 additions & 63 deletions

AGENTS.md

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
### Avoid Type Casting
88

99
We **never ever** cast types unless it's absolutely necessary. This includes:
10+
1011
- Manual generic type parameters (e.g., `<Type>`)
1112
- Type assertions using `as`
1213
- Type assertions using `satisfies`
@@ -15,23 +16,26 @@ We **never ever** cast types unless it's absolutely necessary. This includes:
1516
### Prefer Type Inference
1617

1718
Always infer types and go up the logical chain as far as we can control to determine types. The preferred approach is:
19+
1820
1. **Schema validation** - Use schema definitions (e.g., Convex schema, Zod, etc.) as the source of truth
1921
2. **Type inference from concrete sources** - Let TypeScript infer types from function return types, API responses, etc.
2022
3. **Go up the chain** - Trace types back to their source rather than casting at the point of use
2123

2224
### Example
2325

2426
**Bad:**
27+
2528
```typescript
26-
const result = api.getData() as MyType;
27-
const value = getValue<MyType>();
29+
const result = api.getData() as MyType
30+
const value = getValue<MyType>()
2831
```
2932

3033
**Good:**
34+
3135
```typescript
3236
// Infer from schema or API definition
33-
const result = api.getData(); // Type inferred from api.getData return type
34-
const value = getValue(); // Type inferred from function implementation
37+
const result = api.getData() // Type inferred from api.getData return type
38+
const value = getValue() // Type inferred from function implementation
3539
```
3640

3741
If types need to be fixed, fix them at the source (schema, API definition, function signature) rather than casting at the point of use.
@@ -45,6 +49,7 @@ If types need to be fixed, fix them at the source (schema, API definition, funct
4549
Only include the properties from `search` (or other sources) that are actually used in the loader function. This ensures proper cache invalidation and prevents unnecessary re-runs when unrelated search params change.
4650

4751
**Bad:**
52+
4853
```typescript
4954
loaderDeps: ({ search }) => search, // Includes everything, even unused params
5055
loader: async ({ deps }) => {
@@ -54,6 +59,7 @@ loader: async ({ deps }) => {
5459
```
5560

5661
**Good:**
62+
5763
```typescript
5864
loaderDeps: ({ search }) => ({
5965
page: search.page,
@@ -66,4 +72,3 @@ loader: async ({ deps }) => {
6672
```
6773

6874
This ensures the loader only re-runs when the specific dependencies change, not when unrelated search params (like `expanded`, `viewMode`, etc.) change.
69-

agents/tasks/feed-admin-fixes.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,36 +3,43 @@
33
## Issues Found and Fixed
44

55
### 1. Route Navigation - ✅ FIXED
6+
67
**File**: `src/routes/admin/feed.tsx`
78
**Issue**: Using `/admin/feed/new` which doesn't exist as a route
89
**Fix**: Changed to `/admin/feed/$id` with `params={{ id: 'new' }}`
910

1011
### 2. Navigation Search Params - ✅ FIXED
12+
1113
**File**: `src/routes/admin/feed.tsx`
1214
**Issue**: Direct object assignment to search params
1315
**Fix**: Updated to use function form: `search: (s) => ({ ...s, ...updates })`
1416

1517
### 3. Window Confirm - ✅ FIXED
18+
1619
**File**: `src/routes/admin/feed.tsx`
1720
**Issue**: Using `confirm()` without `window.` prefix
1821
**Fix**: Changed to `window.confirm()`
1922

2023
### 4. Type Error in FeedEntryEditor - ✅ FIXED
24+
2125
**File**: `src/routes/admin/feed.$id.tsx`
2226
**Issue**: `entryQuery` could be `undefined` but type expects `FeedEntry | null`
2327
**Fix**: Added null coalescing: `entryQuery ?? null`
2428

2529
### 5. Unused Imports - ✅ FIXED
30+
2631
**Files**: Multiple admin files
2732
**Issue**: Unused imports causing warnings
2833
**Fix**: Removed unused imports (`useState`, `useEffect`, `validateManualEntry`)
2934

3035
### 6. Library Filter Property - ✅ FIXED
36+
3137
**File**: `src/components/admin/FeedEntryEditor.tsx`
3238
**Issue**: Accessing `lib.visible` property that doesn't exist
3339
**Fix**: Removed filter for non-existent property
3440

3541
### 7. Actions Export - ✅ FIXED
42+
3643
**File**: `src/components/admin/FeedSyncStatus.tsx`
3744
**Issue**: `api.feed.actions` doesn't exist in generated API
3845
**Fix**: Removed `syncAllSources` button and updated to use `useAction` hook. GitHub sync works via `api.feed.github.syncGitHubReleases`.
@@ -41,11 +48,13 @@
4148
## Remaining Issues
4249

4350
### 1. Actions Not Exported
51+
4452
**File**: `convex/feed/actions.ts`
4553
**Issue**: Actions file exists but `api.feed.actions` is not available
4654
**Status**: Need to verify Convex file structure. Actions may need to be in root `convex/` directory or registered differently.
4755

4856
### 2. Route Search Params Type Errors - ✅ FIXED
57+
4958
**File**: `src/routes/admin/feed.tsx`
5059
**Issue**: TypeScript errors with search param updates
5160
**Fix**: Changed from `useNavigate()` to `Route.useNavigate()` and updated search param updates to use object spread instead of function form
@@ -69,4 +78,3 @@
6978
- Delete post
7079
- Toggle visibility
7180
- Toggle featured
72-

agents/tasks/feed-feature-plan.plan.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -506,4 +506,3 @@ src/
506506
3. Backfill recent blog posts
507507
4. Announce feature to users
508508
5. Monitor and iterate based on feedback
509-

agents/tasks/feed-validation-fixes.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,34 +3,41 @@
33
## Issues Found
44

55
### 1. Schema Index Issue - ✅ FIXED
6+
67
**File**: `convex/schema.ts`
78
**Issue**: The `by_library` index on `libraryIds` array field won't work. Convex doesn't support direct array indexing.
89
**Fix**: ✅ Removed the invalid index and added a comment explaining why.
910

1011
### 2. Hydration Warning - ✅ FIXED
12+
1113
**File**: `src/routes/_libraries/feed.tsx`
1214
**Issue**: React hydration mismatch warning due to localStorage access during SSR.
1315
**Fix**: ✅ Updated to use `useMounted` hook to ensure localStorage access only happens client-side.
1416

1517
### 3. Missing sourceId Field
18+
1619
**File**: `convex/schema.ts`
1720
**Issue**: Schema defines `sourceId` in the plan but it's missing from the actual schema.
1821
**Status**: Check if this is needed - if entries need to track original source IDs (e.g., GitHub release ID), add it.
1922

2023
### 4. FeedList Loading State
24+
2125
**File**: `src/components/FeedList.tsx`
2226
**Issue**: Need to verify loading states are properly displayed.
2327
**Status**: Check implementation - should show loading spinner while query is pending.
2428

2529
### 5. Admin Authentication
30+
2631
**File**: `src/routes/admin/feed.tsx`
2732
**Status**: ✅ Working correctly - shows auth prompt when not logged in.
2833

2934
### 6. Filter URL Encoding
35+
3036
**File**: `src/routes/_libraries/feed.tsx`
3137
**Status**: ✅ Working correctly - filters update URL params properly.
3238

3339
### 7. Console Errors
40+
3441
**Issue**: Some unrelated 404 errors for auth endpoints (`/api/auth/display-name/to-string`, `/api/auth/display-name/value-of`)
3542
**Status**: These appear to be unrelated to feed feature - likely existing auth system issues.
3643

@@ -60,4 +67,3 @@
6067
3. Test admin interface with authenticated user
6168
4. Test GitHub sync when webhook is configured
6269
5. Test blog sync functionality
63-

convex/feed/crypto.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ export const verifyGitHubSignature = action({
1717
const crypto = require('crypto')
1818
const hmac = crypto.createHmac('sha256', args.secret)
1919
const digest = 'sha256=' + hmac.update(args.payload).digest('hex')
20-
return crypto.timingSafeEqual(Buffer.from(args.signature), Buffer.from(digest))
20+
return crypto.timingSafeEqual(
21+
Buffer.from(args.signature),
22+
Buffer.from(digest)
23+
)
2124
},
2225
})
23-

convex/feed/queries.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,9 @@ export const getFeedFacetCounts = query({
467467

468468
// Count featured
469469
const featuredEntries = applyFiltersExcept(entries, 'featured')
470-
const featuredCount = featuredEntries.filter((entry) => entry.featured).length
470+
const featuredCount = featuredEntries.filter(
471+
(entry) => entry.featured
472+
).length
471473

472474
return {
473475
sources: sourceCounts,

convex/feed/timestamps.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
/**
22
* Timestamp management for feed entries
3-
*
3+
*
44
* Timestamp semantics:
55
* - publishedAt: When the content was originally published (from source or manually set)
66
* This is the primary timestamp for sorting and display - represents when content was actually published
77
* - createdAt: When the entry was created in our feed system (when we added it to the database)
88
* - updatedAt: When the entry was last modified in our system
99
* - lastSyncedAt: When we last synced from external source (only for auto-synced entries)
1010
* - _createdAt: Convex internal timestamp (automatic, don't use in business logic)
11-
*
11+
*
1212
* Rules:
1313
* - Always sort by publishedAt (when content was published, not when we added it)
1414
* - createdAt should never be used for display/sorting
@@ -72,4 +72,3 @@ export function validatePublishedAt(publishedAt: number): {
7272

7373
return { valid: true }
7474
}
75-

convex/schema.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,12 @@ import { feedCategoryValidator } from './feed/schema'
66

77
// Zod schema for valid capabilities
88
// Valid capabilities list (exported for use throughout the app)
9-
export const VALID_CAPABILITIES = ['admin', 'disableAds', 'builder', 'feed'] as const
9+
export const VALID_CAPABILITIES = [
10+
'admin',
11+
'disableAds',
12+
'builder',
13+
'feed',
14+
] as const
1015
export const CapabilitySchema = z.enum(VALID_CAPABILITIES)
1116
export type Capability = z.infer<typeof CapabilitySchema>
1217

src/components/FeedEntry.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ export function FeedEntry({
253253
className="text-xs font-semibold text-gray-900 dark:text-gray-100 truncate hover:text-blue-600 dark:hover:text-blue-400 transition-colors"
254254
>
255255
{entry.title}
256-
</Link>
256+
</Link>
257257
</TableCell>
258258

259259
{/* Excerpt */}

src/components/FeedFilters.tsx

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,6 @@ export function FeedFilters({
206206
releaseLevelsDiffer ||
207207
(includePrerelease !== undefined && includePrerelease !== true)
208208

209-
210209
// Render filter content (shared between mobile and desktop)
211210
const renderFilterContent = () => (
212211
<>
@@ -216,9 +215,7 @@ export function FeedFilters({
216215
<FilterCheckbox
217216
label="Featured"
218217
checked={featured ?? false}
219-
onChange={() =>
220-
handleFeaturedChange(featured ? undefined : true)
221-
}
218+
onChange={() => handleFeaturedChange(featured ? undefined : true)}
222219
count={facetCounts?.featured}
223220
/>
224221
</div>
@@ -234,9 +231,7 @@ export function FeedFilters({
234231
onSelectNone={() => {
235232
onFiltersChange({ releaseLevels: undefined })
236233
}}
237-
isAllSelected={
238-
selectedReleaseLevels?.length === RELEASE_LEVELS.length
239-
}
234+
isAllSelected={selectedReleaseLevels?.length === RELEASE_LEVELS.length}
240235
isSomeSelected={
241236
selectedReleaseLevels !== undefined &&
242237
selectedReleaseLevels.length > 0 &&
@@ -452,10 +447,7 @@ export function FeedFilters({
452447
compact
453448
/>
454449
)}
455-
<div
456-
onClick={(e) => e.stopPropagation()}
457-
className="flex-shrink-0"
458-
>
450+
<div onClick={(e) => e.stopPropagation()} className="flex-shrink-0">
459451
<FilterSearch
460452
value={searchInput}
461453
onChange={handleSearchChange}
@@ -482,10 +474,7 @@ export function FeedFilters({
482474
>
483475
<LuHelpCircle className="w-4 h-4 text-gray-400 dark:text-gray-500 cursor-help" />
484476
</Tooltip>
485-
<ViewModeToggle
486-
viewMode={viewMode}
487-
onViewModeChange={onViewModeChange}
488-
/>
477+
<ViewModeToggle viewMode={viewMode} onViewModeChange={onViewModeChange} />
489478
</div>
490479
)
491480

@@ -498,8 +487,16 @@ export function FeedFilters({
498487
desktopHeader={desktopHeader}
499488
>
500489
{/* Search - Desktop */}
501-
<div className={`mb-2 lg:block hidden ${viewMode === 'table' ? 'max-w-xs lg:max-w-none lg:w-full' : 'w-full'}`}>
502-
<FilterSearch value={searchInput} onChange={handleSearchChange} className="w-full" />
490+
<div
491+
className={`mb-2 lg:block hidden ${
492+
viewMode === 'table' ? 'max-w-xs lg:max-w-none lg:w-full' : 'w-full'
493+
}`}
494+
>
495+
<FilterSearch
496+
value={searchInput}
497+
onChange={handleSearchChange}
498+
className="w-full"
499+
/>
503500
</div>
504501

505502
{renderFilterContent()}

0 commit comments

Comments
 (0)