style(13-03): apply Prettier formatting across repo
Mechanical reformat — no logic changes. 398 files changed, 19125 insertions(+), 16457 deletions(-). Prettier 3.8.4 with .prettierrc (singleQuote:true, semi:true, tabWidth:2, trailingComma:all, printWidth:100). Isolated per D-13-08 for reviewability.
This commit is contained in:
@@ -102,7 +102,7 @@ writing `isShared` itself, since the DB field controls visibility semantics):
|
||||
```typescript
|
||||
// In PATCH /:id, after the access check at line 327-332:
|
||||
if (patch.isShared !== undefined && !access.isOwner) {
|
||||
return c.json({ error: 'Only the list owner can change sharing settings' }, 403)
|
||||
return c.json({ error: 'Only the list owner can change sharing settings' }, 403);
|
||||
}
|
||||
```
|
||||
|
||||
@@ -124,8 +124,7 @@ fires on channel `list:${newId}`. Member B's open SSE stream has no subscriber o
|
||||
channel — it was computed before the list existed. B only learns about the list when the
|
||||
30-second polling fallback fires (D-12).
|
||||
|
||||
This means the "other member sees the change appear without refreshing" requirement (Truth
|
||||
3) is not met for newly-created shared lists while both members are simultaneously connected.
|
||||
This means the "other member sees the change appear without refreshing" requirement (Truth 3) is not met for newly-created shared lists while both members are simultaneously connected.
|
||||
The 30-second polling fallback (D-12) masks the failure but does not eliminate it.
|
||||
|
||||
**Fix (two options):**
|
||||
@@ -169,9 +168,9 @@ validate the path parameter before touching the DB.
|
||||
**Fix:** Add NaN validation immediately after each `Number(...)` conversion:
|
||||
|
||||
```typescript
|
||||
const listId = Number(c.req.param('id'))
|
||||
const listId = Number(c.req.param('id'));
|
||||
if (!Number.isInteger(listId) || listId < 1) {
|
||||
return c.json({ error: 'Invalid id' }, 400)
|
||||
return c.json({ error: 'Invalid id' }, 400);
|
||||
}
|
||||
```
|
||||
|
||||
@@ -206,15 +205,17 @@ risk is a silent dropped write followed by an eventual crash.
|
||||
|
||||
```typescript
|
||||
subscribeListEvents(listId, (event) => {
|
||||
if (stream.aborted) return
|
||||
stream.writeSSE({
|
||||
data: JSON.stringify(event),
|
||||
event: event.type,
|
||||
id: `${listId}-${Date.now()}`,
|
||||
}).catch((err) => {
|
||||
console.error('[sse/lists] writeSSE failed:', err)
|
||||
})
|
||||
})
|
||||
if (stream.aborted) return;
|
||||
stream
|
||||
.writeSSE({
|
||||
data: JSON.stringify(event),
|
||||
event: event.type,
|
||||
id: `${listId}-${Date.now()}`,
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('[sse/lists] writeSSE failed:', err);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
@@ -302,18 +303,16 @@ test is added simultaneously.
|
||||
|
||||
```typescript
|
||||
it('returns 403 when a sharee attempts to change isShared (owner-only)', async () => {
|
||||
const ownerId = await seedUser('patch-isshared-owner')
|
||||
const shareeId = await seedUser('patch-isshared-sharee')
|
||||
const listId = await seedList(ownerId, 'Shared List', true)
|
||||
await shareList(listId, shareeId)
|
||||
const ownerId = await seedUser('patch-isshared-owner');
|
||||
const shareeId = await seedUser('patch-isshared-sharee');
|
||||
const listId = await seedList(ownerId, 'Shared List', true);
|
||||
await shareList(listId, shareeId);
|
||||
|
||||
currentDevUserId = shareeId
|
||||
const app = await getApp()
|
||||
const res = await app.request(
|
||||
jsonRequest('PATCH', `/api/lists/${listId}`, { isShared: false }),
|
||||
)
|
||||
expect(res.status).toBe(403)
|
||||
})
|
||||
currentDevUserId = shareeId;
|
||||
const app = await getApp();
|
||||
const res = await app.request(jsonRequest('PATCH', `/api/lists/${listId}`, { isShared: false }));
|
||||
expect(res.status).toBe(403);
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
@@ -325,8 +324,8 @@ it('returns 403 when a sharee attempts to change isShared (owner-only)', async (
|
||||
**Issue:** `addMutation.onMutate` computes the optimistic rank using:
|
||||
|
||||
```typescript
|
||||
const lastRank = activeItems.at(-1)?.rank ?? null
|
||||
const optimisticRank = generateKeyBetween(lastRank, null)
|
||||
const lastRank = activeItems.at(-1)?.rank ?? null;
|
||||
const optimisticRank = generateKeyBetween(lastRank, null);
|
||||
```
|
||||
|
||||
`activeItems` is the locally-computed split of the React Query cache at the time the
|
||||
@@ -405,10 +404,8 @@ const rows = await db
|
||||
.selectDistinct({ id: lists.id })
|
||||
.from(lists)
|
||||
.leftJoin(listShares, eq(listShares.listId, lists.id))
|
||||
.where(
|
||||
or(eq(lists.ownerId, userId), eq(listShares.userId, userId)),
|
||||
)
|
||||
return rows.map((r) => r.id)
|
||||
.where(or(eq(lists.ownerId, userId), eq(listShares.userId, userId)));
|
||||
return rows.map((r) => r.id);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Reference in New Issue
Block a user