@idealyst/cli 1.0.44 → 1.0.46
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/templates/native/src/App-with-trpc-and-shared.tsx +4 -258
- package/dist/templates/shared/README.md +31 -5
- package/dist/templates/shared/__tests__/shared.test.ts +17 -5
- package/dist/templates/shared/package.json +7 -28
- package/dist/templates/shared/src/components/HelloWorld.tsx +117 -0
- package/dist/templates/shared/src/components/index.ts +1 -392
- package/dist/templates/shared/src/index.ts +6 -58
- package/dist/templates/shared/tsconfig.json +3 -6
- package/dist/templates/web/src/App-with-trpc-and-shared.tsx +4 -296
- package/package.json +1 -1
- package/templates/native/src/App-with-trpc-and-shared.tsx +4 -258
- package/templates/shared/README.md +31 -5
- package/templates/shared/__tests__/shared.test.ts +17 -5
- package/templates/shared/package.json +7 -28
- package/templates/shared/src/components/HelloWorld.tsx +117 -0
- package/templates/shared/src/components/index.ts +1 -392
- package/templates/shared/src/index.ts +6 -58
- package/templates/shared/tsconfig.json +3 -6
- package/templates/web/src/App-with-trpc-and-shared.tsx +4 -296
- package/dist/templates/shared/rollup.config.js +0 -43
- package/dist/templates/shared/src/types/index.ts +0 -148
- package/dist/templates/shared/src/utils/index.ts +0 -278
- package/templates/shared/rollup.config.js +0 -43
- package/templates/shared/src/types/index.ts +0 -148
- package/templates/shared/src/utils/index.ts +0 -278
|
@@ -1,278 +0,0 @@
|
|
|
1
|
-
// Date and time utilities
|
|
2
|
-
export const formatDate = (date: Date | string): string => {
|
|
3
|
-
const d = typeof date === 'string' ? new Date(date) : date;
|
|
4
|
-
return d.toLocaleDateString('en-US', {
|
|
5
|
-
year: 'numeric',
|
|
6
|
-
month: 'long',
|
|
7
|
-
day: 'numeric'
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
export const formatDateTime = (date: Date | string): string => {
|
|
12
|
-
const d = typeof date === 'string' ? new Date(date) : date;
|
|
13
|
-
return d.toLocaleString('en-US', {
|
|
14
|
-
year: 'numeric',
|
|
15
|
-
month: 'short',
|
|
16
|
-
day: 'numeric',
|
|
17
|
-
hour: '2-digit',
|
|
18
|
-
minute: '2-digit'
|
|
19
|
-
});
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
export const formatRelativeTime = (date: Date | string): string => {
|
|
23
|
-
const d = typeof date === 'string' ? new Date(date) : date;
|
|
24
|
-
const now = new Date();
|
|
25
|
-
const diffInSeconds = Math.floor((now.getTime() - d.getTime()) / 1000);
|
|
26
|
-
|
|
27
|
-
if (diffInSeconds < 60) return 'just now';
|
|
28
|
-
if (diffInSeconds < 3600) return `${Math.floor(diffInSeconds / 60)} minutes ago`;
|
|
29
|
-
if (diffInSeconds < 86400) return `${Math.floor(diffInSeconds / 3600)} hours ago`;
|
|
30
|
-
if (diffInSeconds < 2592000) return `${Math.floor(diffInSeconds / 86400)} days ago`;
|
|
31
|
-
return formatDate(d);
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
// String utilities
|
|
35
|
-
export const truncateText = (text: string, maxLength: number): string => {
|
|
36
|
-
if (text.length <= maxLength) return text;
|
|
37
|
-
return text.substring(0, maxLength).trim() + '...';
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
export const capitalizeFirst = (text: string): string => {
|
|
41
|
-
if (!text) return text;
|
|
42
|
-
return text.charAt(0).toUpperCase() + text.slice(1);
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
export const slugify = (text: string): string => {
|
|
46
|
-
return text
|
|
47
|
-
.toLowerCase()
|
|
48
|
-
.replace(/[^\w\s-]/g, '') // Remove special chars
|
|
49
|
-
.replace(/[\s_-]+/g, '-') // Replace spaces and underscores with hyphens
|
|
50
|
-
.replace(/^-+|-+$/g, ''); // Remove leading/trailing hyphens
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
// Array utilities
|
|
54
|
-
export const paginate = <T>(array: T[], page: number, pageSize: number) => {
|
|
55
|
-
const startIndex = (page - 1) * pageSize;
|
|
56
|
-
const endIndex = startIndex + pageSize;
|
|
57
|
-
|
|
58
|
-
return {
|
|
59
|
-
items: array.slice(startIndex, endIndex),
|
|
60
|
-
total: array.length,
|
|
61
|
-
page,
|
|
62
|
-
pageSize,
|
|
63
|
-
hasMore: endIndex < array.length,
|
|
64
|
-
totalPages: Math.ceil(array.length / pageSize)
|
|
65
|
-
};
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
export const sortBy = <T>(array: T[], key: keyof T, order: 'asc' | 'desc' = 'asc'): T[] => {
|
|
69
|
-
return [...array].sort((a, b) => {
|
|
70
|
-
const aVal = a[key];
|
|
71
|
-
const bVal = b[key];
|
|
72
|
-
|
|
73
|
-
if (aVal < bVal) return order === 'asc' ? -1 : 1;
|
|
74
|
-
if (aVal > bVal) return order === 'asc' ? 1 : -1;
|
|
75
|
-
return 0;
|
|
76
|
-
});
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
// Object utilities
|
|
80
|
-
export const pick = <T extends object, K extends keyof T>(
|
|
81
|
-
obj: T,
|
|
82
|
-
keys: K[]
|
|
83
|
-
): Pick<T, K> => {
|
|
84
|
-
const result = {} as Pick<T, K>;
|
|
85
|
-
keys.forEach(key => {
|
|
86
|
-
if (key in obj) {
|
|
87
|
-
result[key] = obj[key];
|
|
88
|
-
}
|
|
89
|
-
});
|
|
90
|
-
return result;
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
export const omit = <T extends object, K extends keyof T>(
|
|
94
|
-
obj: T,
|
|
95
|
-
keys: K[]
|
|
96
|
-
): Omit<T, K> => {
|
|
97
|
-
const result = { ...obj };
|
|
98
|
-
keys.forEach(key => {
|
|
99
|
-
delete result[key];
|
|
100
|
-
});
|
|
101
|
-
return result as Omit<T, K>;
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
// Validation utilities
|
|
105
|
-
export const isValidEmail = (email: string): boolean => {
|
|
106
|
-
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
107
|
-
return emailRegex.test(email);
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
export const isValidUrl = (url: string): boolean => {
|
|
111
|
-
try {
|
|
112
|
-
new URL(url);
|
|
113
|
-
return true;
|
|
114
|
-
} catch {
|
|
115
|
-
return false;
|
|
116
|
-
}
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
// Local storage utilities (with fallbacks for environments without localStorage)
|
|
120
|
-
export const storage = {
|
|
121
|
-
get: (key: string): string | null => {
|
|
122
|
-
try {
|
|
123
|
-
if (typeof localStorage !== 'undefined') {
|
|
124
|
-
return localStorage.getItem(key);
|
|
125
|
-
}
|
|
126
|
-
} catch (error) {
|
|
127
|
-
console.warn('localStorage not available:', error);
|
|
128
|
-
}
|
|
129
|
-
return null;
|
|
130
|
-
},
|
|
131
|
-
|
|
132
|
-
set: (key: string, value: string): void => {
|
|
133
|
-
try {
|
|
134
|
-
if (typeof localStorage !== 'undefined') {
|
|
135
|
-
localStorage.setItem(key, value);
|
|
136
|
-
}
|
|
137
|
-
} catch (error) {
|
|
138
|
-
console.warn('localStorage not available:', error);
|
|
139
|
-
}
|
|
140
|
-
},
|
|
141
|
-
|
|
142
|
-
remove: (key: string): void => {
|
|
143
|
-
try {
|
|
144
|
-
if (typeof localStorage !== 'undefined') {
|
|
145
|
-
localStorage.removeItem(key);
|
|
146
|
-
}
|
|
147
|
-
} catch (error) {
|
|
148
|
-
console.warn('localStorage not available:', error);
|
|
149
|
-
}
|
|
150
|
-
},
|
|
151
|
-
|
|
152
|
-
getObject: <T>(key: string): T | null => {
|
|
153
|
-
const value = storage.get(key);
|
|
154
|
-
if (value) {
|
|
155
|
-
try {
|
|
156
|
-
return JSON.parse(value);
|
|
157
|
-
} catch (error) {
|
|
158
|
-
console.warn('Failed to parse stored object:', error);
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
return null;
|
|
162
|
-
},
|
|
163
|
-
|
|
164
|
-
setObject: <T>(key: string, value: T): void => {
|
|
165
|
-
try {
|
|
166
|
-
storage.set(key, JSON.stringify(value));
|
|
167
|
-
} catch (error) {
|
|
168
|
-
console.warn('Failed to stringify object for storage:', error);
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
};
|
|
172
|
-
|
|
173
|
-
// Debounce utility for search and input handling
|
|
174
|
-
export const debounce = <T extends (...args: any[]) => any>(
|
|
175
|
-
func: T,
|
|
176
|
-
delay: number
|
|
177
|
-
): ((...args: Parameters<T>) => void) => {
|
|
178
|
-
let timeoutId: NodeJS.Timeout;
|
|
179
|
-
|
|
180
|
-
return (...args: Parameters<T>) => {
|
|
181
|
-
clearTimeout(timeoutId);
|
|
182
|
-
timeoutId = setTimeout(() => func(...args), delay);
|
|
183
|
-
};
|
|
184
|
-
};
|
|
185
|
-
|
|
186
|
-
// Theme utilities
|
|
187
|
-
export const getSystemTheme = (): 'light' | 'dark' => {
|
|
188
|
-
if (typeof window !== 'undefined' && window.matchMedia) {
|
|
189
|
-
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
|
|
190
|
-
}
|
|
191
|
-
return 'light';
|
|
192
|
-
};
|
|
193
|
-
|
|
194
|
-
// Error handling utilities
|
|
195
|
-
export const getErrorMessage = (error: unknown): string => {
|
|
196
|
-
if (error instanceof Error) {
|
|
197
|
-
return error.message;
|
|
198
|
-
}
|
|
199
|
-
if (typeof error === 'string') {
|
|
200
|
-
return error;
|
|
201
|
-
}
|
|
202
|
-
return 'An unexpected error occurred';
|
|
203
|
-
};
|
|
204
|
-
|
|
205
|
-
// Platform detection utilities
|
|
206
|
-
export const isWeb = (): boolean => {
|
|
207
|
-
return typeof window !== 'undefined';
|
|
208
|
-
};
|
|
209
|
-
|
|
210
|
-
export const isMobile = (): boolean => {
|
|
211
|
-
return typeof navigator !== 'undefined' && /Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
|
|
212
|
-
};
|
|
213
|
-
|
|
214
|
-
// Constants for demo data
|
|
215
|
-
export const DEMO_USERS = [
|
|
216
|
-
{
|
|
217
|
-
id: '1',
|
|
218
|
-
name: 'Alice Johnson',
|
|
219
|
-
email: 'alice@example.com',
|
|
220
|
-
avatar: 'https://via.placeholder.com/150/4CAF50/white?text=AJ',
|
|
221
|
-
bio: 'Full-stack developer passionate about React and TypeScript',
|
|
222
|
-
location: 'San Francisco, CA',
|
|
223
|
-
website: 'https://alice-dev.com'
|
|
224
|
-
},
|
|
225
|
-
{
|
|
226
|
-
id: '2',
|
|
227
|
-
name: 'Bob Smith',
|
|
228
|
-
email: 'bob@example.com',
|
|
229
|
-
avatar: 'https://via.placeholder.com/150/2196F3/white?text=BS',
|
|
230
|
-
bio: 'UI/UX designer and frontend enthusiast',
|
|
231
|
-
location: 'New York, NY',
|
|
232
|
-
website: 'https://bobdesigns.co'
|
|
233
|
-
},
|
|
234
|
-
{
|
|
235
|
-
id: '3',
|
|
236
|
-
name: 'Carol Williams',
|
|
237
|
-
email: 'carol@example.com',
|
|
238
|
-
avatar: 'https://via.placeholder.com/150/FF9800/white?text=CW',
|
|
239
|
-
bio: 'Product manager with a love for user research',
|
|
240
|
-
location: 'Austin, TX'
|
|
241
|
-
}
|
|
242
|
-
];
|
|
243
|
-
|
|
244
|
-
export const DEMO_POSTS = [
|
|
245
|
-
{
|
|
246
|
-
id: '1',
|
|
247
|
-
title: 'Getting Started with React Native',
|
|
248
|
-
content: 'React Native is a powerful framework for building cross-platform mobile applications...',
|
|
249
|
-
excerpt: 'Learn the basics of React Native development',
|
|
250
|
-
authorId: '1',
|
|
251
|
-
tags: ['react-native', 'mobile', 'javascript'],
|
|
252
|
-
published: true,
|
|
253
|
-
views: 234,
|
|
254
|
-
likes: 15
|
|
255
|
-
},
|
|
256
|
-
{
|
|
257
|
-
id: '2',
|
|
258
|
-
title: 'Design Systems in Modern Web Development',
|
|
259
|
-
content: 'A design system is a complete set of standards intended to manage design at scale...',
|
|
260
|
-
excerpt: 'Building consistent user interfaces across applications',
|
|
261
|
-
authorId: '2',
|
|
262
|
-
tags: ['design-systems', 'ui-ux', 'frontend'],
|
|
263
|
-
published: true,
|
|
264
|
-
views: 189,
|
|
265
|
-
likes: 23
|
|
266
|
-
},
|
|
267
|
-
{
|
|
268
|
-
id: '3',
|
|
269
|
-
title: 'User Research Best Practices',
|
|
270
|
-
content: 'Understanding your users is crucial for building successful products...',
|
|
271
|
-
excerpt: 'How to conduct effective user research',
|
|
272
|
-
authorId: '3',
|
|
273
|
-
tags: ['user-research', 'product-management', 'ux'],
|
|
274
|
-
published: true,
|
|
275
|
-
views: 156,
|
|
276
|
-
likes: 31
|
|
277
|
-
}
|
|
278
|
-
];
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
const typescript = require('rollup-plugin-typescript2');
|
|
2
|
-
|
|
3
|
-
module.exports = {
|
|
4
|
-
input: 'src/index.ts',
|
|
5
|
-
output: [
|
|
6
|
-
{
|
|
7
|
-
file: 'dist/index.js',
|
|
8
|
-
format: 'cjs',
|
|
9
|
-
exports: 'named',
|
|
10
|
-
sourcemap: true,
|
|
11
|
-
},
|
|
12
|
-
{
|
|
13
|
-
file: 'dist/index.esm.js',
|
|
14
|
-
format: 'esm',
|
|
15
|
-
exports: 'named',
|
|
16
|
-
sourcemap: true,
|
|
17
|
-
},
|
|
18
|
-
],
|
|
19
|
-
plugins: [
|
|
20
|
-
typescript({
|
|
21
|
-
typescript: require('typescript'),
|
|
22
|
-
tsconfig: './tsconfig.json',
|
|
23
|
-
exclude: ['**/*.test.ts', '**/*.test.tsx', '**/*.native.ts', '**/*.native.tsx'],
|
|
24
|
-
declaration: true,
|
|
25
|
-
declarationDir: 'dist',
|
|
26
|
-
rootDir: 'src',
|
|
27
|
-
clean: true,
|
|
28
|
-
}),
|
|
29
|
-
],
|
|
30
|
-
external: [
|
|
31
|
-
'react',
|
|
32
|
-
'react-dom',
|
|
33
|
-
'react-native',
|
|
34
|
-
'react-native-unistyles',
|
|
35
|
-
'@react-native/normalize-colors',
|
|
36
|
-
'react-native-edge-to-edge',
|
|
37
|
-
'react-native-nitro-modules',
|
|
38
|
-
'@react-native-vector-icons/common',
|
|
39
|
-
'@react-native-vector-icons/material-design-icons',
|
|
40
|
-
'@mdi/js',
|
|
41
|
-
'@mdi/react',
|
|
42
|
-
],
|
|
43
|
-
};
|
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
|
|
3
|
-
// User related schemas and types
|
|
4
|
-
export const UserSchema = z.object({
|
|
5
|
-
id: z.string(),
|
|
6
|
-
email: z.string().email(),
|
|
7
|
-
name: z.string().nullable(),
|
|
8
|
-
avatar: z.string().url().nullable(),
|
|
9
|
-
bio: z.string().nullable(),
|
|
10
|
-
location: z.string().nullable(),
|
|
11
|
-
website: z.string().url().nullable(),
|
|
12
|
-
createdAt: z.date(),
|
|
13
|
-
updatedAt: z.date(),
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
export const CreateUserSchema = z.object({
|
|
17
|
-
email: z.string().email(),
|
|
18
|
-
name: z.string().min(1, 'Name is required'),
|
|
19
|
-
avatar: z.string().url().optional(),
|
|
20
|
-
bio: z.string().optional(),
|
|
21
|
-
location: z.string().optional(),
|
|
22
|
-
website: z.string().url().optional(),
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
export const UpdateUserSchema = CreateUserSchema.partial();
|
|
26
|
-
|
|
27
|
-
// Post related schemas and types
|
|
28
|
-
export const PostSchema = z.object({
|
|
29
|
-
id: z.string(),
|
|
30
|
-
title: z.string(),
|
|
31
|
-
content: z.string(),
|
|
32
|
-
excerpt: z.string().nullable(),
|
|
33
|
-
published: z.boolean(),
|
|
34
|
-
tags: z.array(z.string()),
|
|
35
|
-
authorId: z.string(),
|
|
36
|
-
views: z.number(),
|
|
37
|
-
likes: z.number(),
|
|
38
|
-
createdAt: z.date(),
|
|
39
|
-
updatedAt: z.date(),
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
export const CreatePostSchema = z.object({
|
|
43
|
-
title: z.string().min(1, 'Title is required'),
|
|
44
|
-
content: z.string().min(1, 'Content is required'),
|
|
45
|
-
excerpt: z.string().optional(),
|
|
46
|
-
published: z.boolean().default(false),
|
|
47
|
-
tags: z.array(z.string()).default([]),
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
export const UpdatePostSchema = CreatePostSchema.partial();
|
|
51
|
-
|
|
52
|
-
// Comment related schemas and types
|
|
53
|
-
export const CommentSchema = z.object({
|
|
54
|
-
id: z.string(),
|
|
55
|
-
content: z.string(),
|
|
56
|
-
authorId: z.string(),
|
|
57
|
-
postId: z.string(),
|
|
58
|
-
parentId: z.string().nullable(),
|
|
59
|
-
createdAt: z.date(),
|
|
60
|
-
updatedAt: z.date(),
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
export const CreateCommentSchema = z.object({
|
|
64
|
-
content: z.string().min(1, 'Comment cannot be empty'),
|
|
65
|
-
postId: z.string(),
|
|
66
|
-
parentId: z.string().optional(),
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
// User settings schemas and types
|
|
70
|
-
export const UserSettingsSchema = z.object({
|
|
71
|
-
id: z.string(),
|
|
72
|
-
theme: z.enum(['light', 'dark', 'auto']),
|
|
73
|
-
notifications: z.boolean(),
|
|
74
|
-
emailUpdates: z.boolean(),
|
|
75
|
-
publicProfile: z.boolean(),
|
|
76
|
-
userId: z.string(),
|
|
77
|
-
createdAt: z.date(),
|
|
78
|
-
updatedAt: z.date(),
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
export const UpdateUserSettingsSchema = z.object({
|
|
82
|
-
theme: z.enum(['light', 'dark', 'auto']).optional(),
|
|
83
|
-
notifications: z.boolean().optional(),
|
|
84
|
-
emailUpdates: z.boolean().optional(),
|
|
85
|
-
publicProfile: z.boolean().optional(),
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
// Inferred TypeScript types
|
|
89
|
-
export type User = z.infer<typeof UserSchema>;
|
|
90
|
-
export type CreateUser = z.infer<typeof CreateUserSchema>;
|
|
91
|
-
export type UpdateUser = z.infer<typeof UpdateUserSchema>;
|
|
92
|
-
|
|
93
|
-
export type Post = z.infer<typeof PostSchema>;
|
|
94
|
-
export type CreatePost = z.infer<typeof CreatePostSchema>;
|
|
95
|
-
export type UpdatePost = z.infer<typeof UpdatePostSchema>;
|
|
96
|
-
|
|
97
|
-
export type Comment = z.infer<typeof CommentSchema>;
|
|
98
|
-
export type CreateComment = z.infer<typeof CreateCommentSchema>;
|
|
99
|
-
|
|
100
|
-
export type UserSettings = z.infer<typeof UserSettingsSchema>;
|
|
101
|
-
export type UpdateUserSettings = z.infer<typeof UpdateUserSettingsSchema>;
|
|
102
|
-
|
|
103
|
-
// Extended types with relations for UI components
|
|
104
|
-
export type UserWithPosts = User & {
|
|
105
|
-
posts: Post[];
|
|
106
|
-
settings?: UserSettings;
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
export type PostWithAuthor = Post & {
|
|
110
|
-
author: User;
|
|
111
|
-
comments: CommentWithAuthor[];
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
export type CommentWithAuthor = Comment & {
|
|
115
|
-
author: User;
|
|
116
|
-
children?: CommentWithAuthor[];
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
// API Response types
|
|
120
|
-
export type ApiResponse<T> = {
|
|
121
|
-
data: T;
|
|
122
|
-
success: boolean;
|
|
123
|
-
message?: string;
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
export type PaginatedResponse<T> = ApiResponse<{
|
|
127
|
-
items: T[];
|
|
128
|
-
total: number;
|
|
129
|
-
page: number;
|
|
130
|
-
pageSize: number;
|
|
131
|
-
hasMore: boolean;
|
|
132
|
-
}>;
|
|
133
|
-
|
|
134
|
-
// Common utility types
|
|
135
|
-
export type Theme = 'light' | 'dark' | 'auto';
|
|
136
|
-
|
|
137
|
-
export interface LoadingState {
|
|
138
|
-
isLoading: boolean;
|
|
139
|
-
error?: string;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
export interface PaginationParams {
|
|
143
|
-
page?: number;
|
|
144
|
-
pageSize?: number;
|
|
145
|
-
sortBy?: string;
|
|
146
|
-
sortOrder?: 'asc' | 'desc';
|
|
147
|
-
search?: string;
|
|
148
|
-
}
|