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
4 changes: 2 additions & 2 deletions apps/expo/features/catalog/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@ export interface CatalogItem {

embedding?: number[] | null; // vector(1536)

createdAt: string;
updatedAt: string;
createdAt: string | Date;
updatedAt: string | Date;
}

export type CatalogItemWithQuantity = CatalogItem & { quantity?: number };
Expand Down
1 change: 1 addition & 0 deletions packages/app/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ export { useCreatePackMutation } from './src/features/pack/create/queries';
export { useCreateTripMutation } from './src/features/trip/create/queries';
export * from './src/shared/api';
export * from './src/shared/lib/date';
export * from './src/shared/lib/uuid';
export * from './src/shared/lib/weight';
4 changes: 2 additions & 2 deletions packages/app/src/entities/catalog/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export function useCatalogItemsInfinite({
}: UseCatalogItemsParams) {
const client = useApiClient();
return useInfiniteQuery({
queryKey: queryKeys.catalogInfinite(query, category),
queryKey: queryKeys.catalogInfinite({ search: query, category, limit, sort }),
queryFn: async ({ pageParam = 1 }) => {
const { data, error } = await client.catalog.get({
query: {
Expand All @@ -38,7 +38,7 @@ export function useCatalogItemsInfinite({
...(sort ? { sort } : {}),
},
});
if (error) throw new Error(`Failed to fetch catalog items: ${String(error)}`);
if (error) throw new Error(`Failed to fetch catalog items: ${error.value}`);
const parseResult = CatalogItemsResponseSchema.safeParse(data);
if (parseResult.success) return parseResult.data;
return {
Expand Down
2 changes: 1 addition & 1 deletion packages/app/src/entities/feed/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export function useFeed() {
const { data, error } = await client.feed.get({
query: { page: pageParam as number, limit: 20 },
});
if (error) throw new Error(`Failed to fetch feed: ${String(error)}`);
if (error) throw new Error(`Failed to fetch feed: ${error.value}`);
return data;
},
getNextPageParam: (lastPage) => {
Expand Down
3 changes: 2 additions & 1 deletion packages/app/src/features/pack/add-item/queries.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { queryKeys, useApiClient } from '../../../shared/api';
import { generateId } from '../../../shared/lib/uuid';

interface AddPackItemInput {
name: string;
Expand All @@ -22,7 +23,7 @@ export function useAddPackItemMutation() {
mutationFn: async ({ packId, body }: { packId: string; body: AddPackItemInput }) => {
const { data, error } = await client.packs({ packId }).items.post({
...body,
id: crypto.randomUUID(),
id: generateId(),
quantity: body.quantity ?? 1,
consumable: body.consumable ?? false,
worn: body.worn ?? false,
Expand Down
3 changes: 2 additions & 1 deletion packages/app/src/features/pack/create/queries.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { queryKeys, useApiClient } from '../../../shared/api';
import { generateId } from '../../../shared/lib/uuid';

interface CreatePackInput {
name: string;
Expand All @@ -18,7 +19,7 @@ export function useCreatePackMutation() {
const now = new Date().toISOString();
const { data, error } = await client.packs.post({
...input,
id: crypto.randomUUID(),
id: generateId(),
isPublic: input.isPublic ?? false,
localCreatedAt: now,
localUpdatedAt: now,
Expand Down
3 changes: 2 additions & 1 deletion packages/app/src/features/trip/create/queries.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { queryKeys, useApiClient } from '../../../shared/api';
import { generateId } from '../../../shared/lib/uuid';

interface CreateTripInput {
name: string;
Expand All @@ -19,7 +20,7 @@ export function useCreateTripMutation() {
const now = new Date().toISOString();
const { data, error } = await client.trips.post({
...input,
id: crypto.randomUUID(),
id: generateId(),
localCreatedAt: now,
localUpdatedAt: now,
});
Expand Down
10 changes: 8 additions & 2 deletions packages/app/src/shared/api/query-keys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,14 @@ export const queryKeys = {
trip: (id: string) => ['trip', id] as const,
catalog: (opts: { page?: number; search?: string; category?: string } = {}) =>
['catalog', { page: opts.page ?? 1, search: opts.search, category: opts.category }] as const,
catalogInfinite: (search?: string, category?: string) =>
['catalogInfinite', { search, category }] as const,
catalogInfinite: (
opts: {
search?: string;
category?: string;
limit?: number;
sort?: { field: string; order: string };
} = {},
) => ['catalogInfinite', opts] as const,
Comment on lines +9 to +16

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Tighten the sort.order type from string to 'asc' | 'desc'.

order: string allows any string at the call site, silently accepting values the API will reject. Since this is a query-key factory, the type drives what callers pass and what ends up in cache keys.

🔧 Proposed fix
  catalogInfinite: (
    opts: {
      search?: string;
      category?: string;
      limit?: number;
-     sort?: { field: string; order: string };
+     sort?: { field: string; order: 'asc' | 'desc' };
    } = {},
  ) => ['catalogInfinite', opts] as const,
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
catalogInfinite: (
opts: {
search?: string;
category?: string;
limit?: number;
sort?: { field: string; order: string };
} = {},
) => ['catalogInfinite', opts] as const,
catalogInfinite: (
opts: {
search?: string;
category?: string;
limit?: number;
sort?: { field: string; order: 'asc' | 'desc' };
} = {},
) => ['catalogInfinite', opts] as const,
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/app/src/shared/api/query-keys.ts` around lines 9 - 16, The
catalogInfinite query-key factory currently types sort.order as string which
permits invalid values; change the opts type in catalogInfinite so that sort: {
field: string; order: 'asc' | 'desc' } (tighten order to the literal union) so
callers and cache keys only accept 'asc' or 'desc'—update the catalogInfinite
function signature/type annotation accordingly (refer to catalogInfinite and its
opts.sort.order) to enforce the narrowed type throughout the codebase.

catalogItem: (id: number) => ['catalogItem', id] as const,
feed: (page = 1, filter?: 'trending' | 'recent' | 'following') =>
['feed', { page, filter }] as const,
Expand Down
10 changes: 10 additions & 0 deletions packages/app/src/shared/lib/uuid.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// crypto.randomUUID() is not available in older React Native (Hermes < 0.71).
// crypto.getRandomValues() is available since RN 0.60 via the Hermes polyfill.
Comment on lines +1 to +2
export function generateId(): string {
const bytes = new Uint8Array(16);
crypto.getRandomValues(bytes);
bytes[6] = ((bytes[6] ?? 0) & 0x0f) | 0x40;
bytes[8] = ((bytes[8] ?? 0) & 0x3f) | 0x80;
const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('');
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
}
Loading